为了这个问题,假设我正在将 betoh16() 等实现为名为 OpSys 的 C++ 类中的方法。这样做时,我注意到所有 12 个左右的函数大部分都是相同的,我不想重复这么多源代码。
我可以选择使用预处理器执行以下操作...
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
#define BETOH_XX(nbits) \
U##nbits OpSys::betoh##nbits, U##nbits val) \
{ \
if (CPU_IS_BIG_ENDIAN) \
return val; \
\
return bswap##nbits(val); \
}
BETOH_XX(16)
BETOH_XX(32)
BETOH_XX(64)
...但我想知道是否有某种方法可以用模板完成同样的事情,我的调用看起来像
U16 hval = betoh<16>(beval);
我在 SO 上看到了一些关于 templates with constant values 的其他问题,但似乎没有将该模板化值连接到某些相邻文本。
这可能吗?
最佳答案
我认为连接任意模板值以形成新标识符是不可能的(或者应该是,它会破坏提供的额外安全模板)。但是,(如评论中所述)可以为您的特定示例存档类似的内容。
获取所需的语法
U16 hval = betoh<16>(beval);
首先需要从其位大小中获取其中一种固定大小的整数类型。在这个视频中http://www.youtube.com/watch?v=MvFj8qo1iuA , Andrei Alexandrescu 在 19:45 左右展示了一个很好的方法。基本上,您只需声明一个带有 typedef 类型成员的模板结构,并仅针对那些可用的类型专门化它,而对所有其他类型保持未定义状态:
template <size_t bitsize> struct uint_bits;
template<> struct uint_bits<8>{typedef uint8_t type;};
template<> struct uint_bits<16>{typedef uint16_t type;};
template<> struct uint_bits<32>{typedef uint32_t type;};
有了这个,您需要做的就是模板 betoh 和 bswap:
template <size_t bitsize>
typename uint_bits<bitsize>::type bswap(typename uint_bits<bitsize>::type value)
{
typename uint_bits<bitsize>::type ret_val=0;
for(size_t b=0;b<sizeof(value);++b)
{
ret_val<<=8;
ret_val|=(value&0xff);
value>>=8;
}
return ret_val;
}
template <size_t bitsize>
typename uint_bits<bitsize>::type betoh(typename uint_bits<bitsize>::type value)
{
if(CPU_IS_BIG_ENDIAN)
return value;
return bswap<bitsize>(value);
}
这可以通过明确说明位数来使用,恕我直言,有点冗长,使实现复杂化并将函数限制为已知类型,尽管它们可以使用任意无符号整数:
template <typename T>
T bswap(T value)
{
T ret_val=0;
for(size_t b=0;b<sizeof(value);++b)
{
ret_val<<=8;
ret_val|=(value&0xff);
value>>=8;
}
return ret_val;
}
template <typename T>
T betoh(T value)
{
if(CPU_IS_BIG_ENDIAN)
return value;
return bswap(value);
}
这不需要 uint_bits 结构,并且允许将上述调用重写为简单
U16 hval = betoh(beval);
我不确定这些是否实用和/或有效,所以 ;-)。
关于c++ - 与 C++ 模板的预处理器式连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24348454/