如何用模板元编程完成这个复杂的映射

How to accomplish this complex mapping with template metaprogramming?

本文关键字:复杂 映射 何用模 编程      更新时间:2023-10-16

我试图使用模板元编程来定义一个结构体,但我想做的可能需要分布在多个结构体上,而不是有一个超结构体:

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字节),a将是结构体的总长度。

一些例子(不完全是需要的,但给一个想法):

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;
}

要用常量定义结构体,您可以使用普通模板:

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;

如果您需要任意数量的这样的对,则可以使用可变模板进行推广。我将常量设置为静态,因为它们是类型的属性,而不是实例的属性。使用构造函数,这可以很容易地扩展到非整型。

这可能不是你想要的,所以如果我误解了,请留下评论,或者更新你的问题来澄清规格。

您想要做什么并不十分清楚,但从我收集的信息来看,这里是这样的。看看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不需要前两个const的存储空间,它们是类型的一部分-这意味着对于序列化,您需要提供一个特定的方法来序列化id类型和长度(模板参数)-但这是微不足道的。

您似乎正在寻找的是一种指定模板类的方法,该模板类包装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,因为它有专门设计用于此的库。否则,我猜只是打开boost代码并复制它是如何做到的。