C++ 根据模板整数参数选择整数类型
我想创建一个类模板,它接受一个无符号整数参数,并有一个成员u_uu,其类型是保存整数参数的最小无符号整数类型 因此: 对于A,u_u应为uint8_ut类型。A也一样。对于A,u_u应为uint16_uT等类型C++ 根据模板整数参数选择整数类型,c++,templates,C++,Templates,我想创建一个类模板,它接受一个无符号整数参数,并有一个成员u_uu,其类型是保存整数参数的最小无符号整数类型 因此: 对于A,u_u应为uint8_ut类型。A也一样。对于A,u_u应为uint16_uT等类型 如何实现这一点?您可以使用部分绑定模板的声明: template<uint8_t k> using A_uint8 = A<k, uint8_t>; template<uint8_t k> using A_uint16 = A<k, uint1
如何实现这一点?您可以使用部分绑定模板的声明:
template<uint8_t k>
using A_uint8 = A<k, uint8_t>;
template<uint8_t k>
using A_uint16 = A<k, uint16_t>;
然后:
这一元编程技巧实现了这一点:
template<unsigned int Y> struct typed
{
typedef typename typed<(Y & (Y - 1)) == 0 ? Y / 2 : (Y & (Y - 1))>::type type;
};
template<> struct typed<0>
{
typedef std::uint8_t type;
};
template<> struct typed<256>
{
typedef std::uint16_t type;
};
template<> struct typed<65536>
{
typedef std::uint32_t type;
};
/* ToDo - add more specialisations as necessary*/
template<unsigned k> class A
{
public:
unsigned static const k_ = k; /*constexpr if your compiler supports it*/
typename typed<k>::type u_;
};
用法正是问题所在
非专用模板版本采用以前的类型。类型化阻塞了静态递归。其他专业作为适当类型的锚定点
编译时可计算的Y&Y-1==0?Y/2:Y&Y-1通过删除Y的最右边的位来减少实例化的数量,直到达到2的幂,然后再除以2。确认@Jarod42。使用C++11可以使用:
非常感谢。你们太棒了! 顺便说一下,我正在使用:
typedef typename std::conditional<k <= UINT8_MAX,
std::uint8_t,
typename std::conditional<k <= UINT16_MAX,
std::uint16_t,
typename std::conditional<k <= UINT32_MAX,
std::uint32_t,
std::uint64_t>::type>::type>::type TypeU;
std::pair<TypeU, std::shared_ptr<ProtoData>> min_;
std::pair<TypeU, std::shared_ptr<ProtoData>> max_;
如果我们想要的是:给定一个uint64_t模板参数,给出能够表示它的最小无符号类型,那么我们真正想要的只是编译时的一个简单迭代
namespace details {
template <typename T>
struct tag {
using type = T;
};
// base case: just fail
template <uint64_t V, typename... >
struct min_unsigned_type;
// recursive case: check using numeric_limits
template <uint64_t V, typename T, typename... Ts>
struct min_unsigned_type<V, T, Ts...>
: std::conditional_t<(V <= std::numeric_limits<T>::max()),
tag<T>,
min_unsigned_type<V, Ts...>>
{ };
}
然后,只需一个别名即可将所有内容打包:
template <uint64_t V>
using min_unsigned_type =
typename details::min_unsigned_type<V,
uint8_t, uint16_t, uint32_t, uint64_t>::type;
这样做的另一个好处是,可以轻松指定要执行的操作,甚至可以在必要时添加更大的无符号类型
最后,你们班:
template <uint64_t V>
struct A {
static constexpr uint64_t k_ = V;
min_unsigned_type<V> u_;
};
如果k是一个单位,那么这意味着什么?:…=A.256超出了uint8的承受能力,所以这对我来说没有意义谁投票支持了这个问题??它毫无意义,直到我花了一段时间从答案中推断出问题的真正目的。当k的类型为uint8\t时,256怎么可能是参数?允许的最大k是255k,正如@AaronMcDaid指出的问题一样,这并不能解决自动选择类型的原始问题,而不是由调用API的代码手动完成。我在自动选择中看到的主要优点是宏和常量可以用于k,并且类型将使用宏或常量自动更新。
typedef typename std::conditional<k <= UINT8_MAX,
std::uint8_t,
typename std::conditional<k <= UINT16_MAX,
std::uint16_t,
typename std::conditional<k <= UINT32_MAX,
std::uint32_t,
std::uint64_t>::type>::type>::type TypeU;
std::pair<TypeU, std::shared_ptr<ProtoData>> min_;
std::pair<TypeU, std::shared_ptr<ProtoData>> max_;
template<uintmax_t Id>
struct A;
template<>
struct A<0>{
enum {id = 0};
using type = uint8_t;
};
template<>
struct A<255>{
enum {id = 255};
using type = uint8_t;
};
template<>
struct A<256>{
enum {id = 256};
using type = uint16_t;
};
int main(){
typename A<255>::type a0 = 255; // uint8_t
typename A<256>::type a1 = 256; // uint16_t
}
template<uintmax_t Value>
struct A{
enum {value = Value};
using type = std::conditional_t<
(Value <= std::numeric_limits<uint8_t>::max()), uint8_t,
std::conditional_t<
(Value <= std::numeric_limits<uint16_t>::max()), uint16_t,
std::conditional_t<
(Value <= std::numeric_limits<uint32_t>::max()), uint32_t
std::conditional_t<
(Value <= std::numeric_limits<uint64_t>::max()), uint64_t, uintmax_t
>
>
>
>;
};
namespace details {
template <typename T>
struct tag {
using type = T;
};
// base case: just fail
template <uint64_t V, typename... >
struct min_unsigned_type;
// recursive case: check using numeric_limits
template <uint64_t V, typename T, typename... Ts>
struct min_unsigned_type<V, T, Ts...>
: std::conditional_t<(V <= std::numeric_limits<T>::max()),
tag<T>,
min_unsigned_type<V, Ts...>>
{ };
}
template <uint64_t V>
using min_unsigned_type =
typename details::min_unsigned_type<V,
uint8_t, uint16_t, uint32_t, uint64_t>::type;
template <uint64_t V>
struct A {
static constexpr uint64_t k_ = V;
min_unsigned_type<V> u_;
};