预处理器风格的c++模板连接
Preprocessor-style concatenation with C++ templates?
为了解决这个问题,假设我在一个名为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);
我不确定这些是否实用和/或有效,所以;-)。
相关文章:
- 当套接字连接断开时检测C/C++Unix
- 无法在windows上使用mingw将sqlite3与c连接
- 到连接组件算法的问题(递归)
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 无法在C++中建立与MySQL数据库的连接
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- 使用 bfs 解决连接组件问题时得到错误的答案
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
- 在 libcurl 连接池中预创建连接
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- libcurl 和 DNS ttl 中的内部连接管理
- 如何应用 libcurl 的持久连接选项
- 提升 ASIO - io_service 不要等待连接到线程
- WinSock2:connect() 提供"连接被拒绝"
- 升压信号2将插槽传递到成员功能以断开连接