Как выполнить это сложное отображение с помощью шаблонного метапрограммирования? - PullRequest
1 голос
/ 21 сентября 2011

Я пытаюсь определить структуру с помощью шаблонного метапрограммирования, но то, что я пытаюсь сделать, может потребоваться распределить по нескольким структурам вместо одной суперструктуры:

template <A, B, C>
struct ABC
{
   A a;
   B b;
   C c;
}

Вот гибкость, которую я надеюсь достичь, так как я буду использовать генератор кода и предпочел бы не определять каждый возможный тип структуры, если это вообще возможно:

  1. Могут быть определены типы для A, B и C.
  2. a, b или c могут быть предопределенными и предварительно назначенными константами (т. Е. Const unsigned char a = 0x48;) или быть типами элементов регулярных переменных.

Общая схема такова, что в моем кодогенераторе будет числовой ввод без знака для b, c обычно будет целым числом (длиной 1-8 байт), а итоговая длина структуры будет являться результатом.

Некоторые примеры (не совсем то, что нужно, но чтобы дать представление):

struct <struct1>
{
   const unsigned char a = 'A';
   const unsigned short b = 0x1000;
   char c[10];
}

Я не знаю достаточно о шаблонном метапрограммировании, чтобы даже начать делать это, особенно для частей a и b, где они могут быть предварительно назначены или нет.

Возможно, чтобы не усложнять ситуацию, мы можем отказаться от предположения, что я всегда буду присваивать значения A, B, C и a, а b, так что a и b могут быть константами и предварительно назначаться.

В конце эти сообщения будут преобразованы в char * и отправлены по проводам (и упакованы в байты с помощью #pragma)

Заранее спасибо за помощь!

Извините за запутанное описание проблемы. Я попытаюсь прояснить это с некоторыми примерами того, что я хотел бы достичь, используя шаблонную структуру ABC (или дополнительные структуры, определенные по мере необходимости). Эти примеры с точки зрения конечного пользователя:

typedef ABC<100, char[10]> Msg1;

приведет к эквиваленту:

struct Msg1
{
    const unsigned short a = sizeof(Msg1); // sizeof(Msg1) fits in unsigned short
    const unsigned char b = 100;
    char[512] c;
}

Обратите внимание, что размер элементов a и b должен определяться шаблоном на основе размера Msg1 и переданного параметра 100. Это сложная часть для меня.

typedef ABC<23000, unsigned int> Msg2;

struct Msg2
{
    const unsigned char a = sizeof(Msg2);  // sizeof(Msg2) fits in unsigned char
    const unsigned short b = 23000;
    unsigned int c;
}

Надеюсь, это немного прояснит ситуацию.

Ответы [ 3 ]

2 голосов
/ 21 сентября 2011

Ну, чтобы определить структуру с константами, вы можете просто использовать простые шаблоны:

template <typename A, A a_val,
          typename B, B a_val,
          typename C, C a_val>
struct ABC
{
  static const A a = a_val;
  static const B b = b_val;
  static const C c = c_val;
}

Это работает, пока типы являются целыми. Использование:

ABC<char, 'a', unsigned int, 12, std::size_t, 100> abc;

Если вам нужно произвольное количество таких пар, это можно обобщить с помощью шаблонов с переменными числами. Я сделал константы статическими, поскольку они являются свойством типа, а не экземпляра. Используя конструктор, это можно легко распространить на нецелые типы.

Возможно, это не совсем то, что вам нужно, поэтому, если я неправильно понял, оставьте комментарий, или обновите ваш вопрос, чтобы уточнить спецификации.

1 голос
/ 21 сентября 2011

Не совсем ясно, что вы хотите сделать, но из того, что я могу собрать, здесь идет речь. Посмотрите на boost::fusion - может сэкономить некоторые усилия. Например:

typedef unsigned char IDType
typedef unsigned short LengthType
typedef boost::array<char, 8> DataType

typedef boost::fusion::vector<IDType, LengthType, DataType> StructA;

StructA a_inst('A',0x1000, "ABCD");

Это создает экземпляр StructA с заданными значениями, теперь, если вы можете гарантировать, что первые два атрибута всегда постоянны - вы можете сделать что-то вроде этого:

typedef <unsigned char id, unsigned short len, typename DataType>
struct generic_struct
{
  DataType _data;
};

// Now a specific type looks like this
typedef generic_struct<'A', 0x1000, boost::array<char, 8> > StructA;

Разница с последним подходом заключается в том, что StructA не требует места для хранения для первых двух констант, они являются частью типа - это означает для сериализации, вам необходимо предоставить конкретный метод который может сериализовать тип и длину идентификатора (параметры шаблона), но это тривиально.

0 голосов
/ 21 сентября 2011

То, что вы, похоже, ищете, - это способ указать класс шаблона, который оборачивает 2 члена и добавляет дополнительный член, который содержит sizeof для этого шаблона.

template <int B, class C>
struct tABC
{
    const size_t a;
    const unsigned int b;
    C c;

    tABC() : a(sizeof(*this)), b(B) {}
};

, который генерирует в основном код, который выпохоже ищет.Единственное, чего не хватает, так это того, что у вас, похоже, есть некоторые правила выбора типа a и b.Если это «какой бы ни был наименьший тип, который мог бы их содержать», вам действительно нужно подумать об использовании boost, поскольку он имеет библиотеки, предназначенные именно для этого.В противном случае, я думаю, просто откройте буст-код и скопируйте, как он это делает.

...