我试图创建一个用于处理比特流的模板类。我希望模板中声明的基础整数类型可以解析为uint8_t
,uint16_t
,uint32_t
或uint64_t
,具体取决于模板参数(int,位数)。我找到了关于这个主题的两个答案(How can I specialize a C++ template for a range of integer values?和Integer range based template specialisation)并实现了以下代码:
template<int BITS>
class MyClass {
typedef typename
std::conditional< BITS <= 8, uint8_t,
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > > >::type
int_type;
...
}
在我的程序中,我实例化MyClass<32>
,但在编译时,我收到以下错误:
no known conversion for argument 1 from ‘uint32_t {aka unsigned int}’ to ‘MyClass<32>::int_type {aka std::conditional<false, short unsigned int, std::conditional<true, unsigned int, long unsigned int> >}’
如果我实例化MyClass<8>
,那么一切正常。所以看起来只有std::conditional
的第一级实际上是扩展的。
知道如何正确地做到这一点吗?
编辑:我之前没有说过这个,但我正在寻找一个适用于任何比特大小实例化的解决方案(只要它能够实现)最多64位)。所以我希望MyClass<27>
能够正常工作(选择uint32_t
)。
答案 0 :(得分:6)
最简单的越好:
template<unsigned nbits> struct uint {};
template<> struct uint<8> { using type = uint8_t; };
template<> struct uint<16> { using type = uint16_t; };
template<> struct uint<32> { using type = uint32_t; };
template<> struct uint<64> { using type = uint64_t; };
template<int nbits>
struct MyClass { using int_type = typename uint<(nbits/8)*8>::type; };
答案 1 :(得分:2)
回答编辑并使原始代码正常工作。
template<int BITS>
class MyClass {
using int_type =
typename std::conditional< BITS <= 8, uint8_t,
typename std::conditional< BITS <= 16, uint16_t,
typename std::conditional< BITS <= 32, uint32_t, uint64_t >::type >::type >::type;
public:
int_type i;
};
答案 2 :(得分:0)
问题的解决方案已在the answer by @super中提供。
了解错误信息对我很有帮助。
您已将int_type
定义为:
typedef typename
std::conditional< BITS <= 8, uint8_t,
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > > >::type
int_type;
自
以来,BITS <= 8
正常运行
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > >
部分基本上被忽略了。
我们假设您使用MyClass<16>
。然后,忽略uint8_t
。你对int_type
的所作所为:
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > >
可以简化为:
std::conditional< true, uint16_t,
std::conditional< true, uint32_t, uint64_t > >
不幸的是,这是您在不使用std::conditional<...>::type
的情况下获得的类型。
我们假设您使用MyClass<32>
。那么你对int_type
所拥有的是:
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > >
可以简化为:
std::conditional< false, uint16_t,
std::conditional< true, uint32_t, uint64_t > >
这是你得到的类型。
您可以通过打印相应type_info
个对象的名称来了解这些类型。
示例程序:
#include <iostream>
#include <typeinfo>
#include <type_traits>
#include <cstdint>
template<int BITS>
struct MyClass
{
typedef typename
std::conditional< BITS <= 8, uint8_t,
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > > >::type
int_type;
};
int main()
{
typename MyClass<8>::int_type a;
std::cout << typeid(a).name() << std::endl;
typename MyClass<16>::int_type b;
std::cout << typeid(b).name() << std::endl;
typename MyClass<32>::int_type c;
std::cout << typeid(c).name() << std::endl;
typename MyClass<60>::int_type d;
std::cout << typeid(d).name() << std::endl;
}
输出,使用g ++ 5.4.0:
h
St11conditionalILb1EtS_ILb1EjmEE
St11conditionalILb0EtS_ILb1EjmEE
St11conditionalILb0EtS_ILb0EjmEE