预处理器风格的c++模板连接

Preprocessor-style concatenation with C++ templates?

本文关键字:连接 c++ 处理器 风格 预处理      更新时间:2023-10-16

为了解决这个问题,假设我在一个名为OpSys的c++类中将betoh16()等作为方法实现。在这样做的时候,我注意到所有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上看到了一些关于带有常数值的模板的其他问题,但似乎没有使用该模板化值与相邻文本连接的问题。

这可能吗?

我不相信将任意模板值连接起来形成新的标识符是可能的(或者应该是可能的,因为这会破坏模板提供的额外安全)。但是,(正如在评论中提到的)可以为您的特定示例归档类似的内容。

获取所需的语法

U16 hval = betoh<16>(beval);

首先需要从它的位大小中获得一个固定大小的整数类型。在这个视频http://www.youtube.com/watch?v=MvFj8qo1iuA中,Andrei Alexandrescu在19:45左右展示了一种很好的方法。基本上,您只需声明一个带有类型定义类型成员的模板结构,并仅针对那些可用的类型对其进行特化,同时对所有其他类型保持未定义:

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

我不确定这些是否实用和/或有效,所以;-)。