我有一个具有整数模板参数N
的类。
template<unsigned int N>
class test {
}
现在我希望std::vector
具有尽可能小的整数类型来保存N
位。
E.g。
class test<8> {
std::vector<uint8_t> data;
}
class test<9> {
std::vector<uint16_t> data;
}
class test<10> {
std::vector<uint16_t> data;
}
...
对于N=1
到N=64
,还有更好的方法吗?
答案 0 :(得分:3)
使用条件怎么样?
#include <vector>
#include <cstdint>
#include <iostream>
#include <type_traits>
template <std::size_t N>
struct foo
{
static_assert( N < 65U, "foo 64 limit");
using vType = typename std::conditional<
(N < 9U), std::uint8_t,
typename std::conditional< (N < 17U), std::uint16_t,
typename std::conditional< (N < 33U), std::uint32_t, std::uint64_t
>::type>::type>::type;
std::vector<vType> data;
};
int main()
{
static_assert( 1U == sizeof(foo<1>::vType), "!");
static_assert( 1U == sizeof(foo<8>::vType), "!");
static_assert( 2U == sizeof(foo<9>::vType), "!");
static_assert( 2U == sizeof(foo<16>::vType), "!");
static_assert( 4U == sizeof(foo<17>::vType), "!");
static_assert( 4U == sizeof(foo<32>::vType), "!");
static_assert( 8U == sizeof(foo<33>::vType), "!");
static_assert( 8U == sizeof(foo<64>::vType), "!");
// foo<65> f65; compilation error
}
或者,以更优雅的方式(恕我直言),您可以定义一个类型特征(在下面的示例中为selectTypeByDim
),用于选择列表中的第一个有用类型
#include <tuple>
#include <vector>
#include <cstdint>
#include <climits>
#include <type_traits>
template <std::size_t N, typename T,
bool = (N <= sizeof(typename std::tuple_element<0U, T>::type)*CHAR_BIT)>
struct stbdH;
template <std::size_t N, typename T0, typename ... Ts>
struct stbdH<N, std::tuple<T0, Ts...>, true>
{ using type = T0; };
template <std::size_t N, typename T0, typename ... Ts>
struct stbdH<N, std::tuple<T0, Ts...>, false>
{ using type = typename stbdH<N, std::tuple<Ts...>>::type; };
template <std::size_t N, typename ... Ts>
struct selectTypeByDim : stbdH<N, std::tuple<Ts...>>
{ };
template <std::size_t N>
struct foo
{
static_assert( N < 65U, "foo 64 limit");
using vType = typename selectTypeByDim<N,
std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>::type;
std::vector<vType> data;
};
int main()
{
static_assert( 1U == sizeof(foo<1U>::vType), "!");
static_assert( 1U == sizeof(foo<CHAR_BIT>::vType), "!");
static_assert( 2U == sizeof(foo<CHAR_BIT+1U>::vType), "!");
static_assert( 2U == sizeof(foo<(CHAR_BIT<<1)>::vType), "!");
static_assert( 4U == sizeof(foo<(CHAR_BIT<<1)+1U>::vType), "!");
static_assert( 4U == sizeof(foo<(CHAR_BIT<<2)>::vType), "!");
static_assert( 8U == sizeof(foo<(CHAR_BIT<<2)+1U>::vType), "!");
static_assert( 8U == sizeof(foo<(CHAR_BIT<<3)>::vType), "!");
//foo<(CHAR_BIT<<3)+1U> f65; compilation error
}
答案 1 :(得分:1)
根据您对问题的评论,您实际上并不需要内置类型。任何可复制的可移动对象都可以放入向量中。
如果要对数据进行排序,我建议使用自定义{{std::bitset<2*N>
或std::array<std::byte, (2*N+7)/8>
(或std::array<std::byte,
(2*N+CHAR_BIT-1)/CHAR_BIT>
,如果您在一个奇怪的系统上运行) 1}}用于排序。如果你有任何其他用途(你可能会这样做),我会建议一个自定义类,其中一个作为其底层存储;这使您可以添加更多功能,例如获取特定的基础。
在大多数系统上,如果Compare
是32或64的倍数(取决于实现),std::bitset
将没有开销,但这不能保证。字节数组的开销通常不会超过C ++所需的开销。如果需要,这两个都可以扩展到超过64位,并且字节数组将具有最小的空间开销,甚至比使用整数类型更少,因为它不会强制大小为2的幂。在其中任何一个上添加自定义类都不会产生任何开销。
(如果您使用的是C ++ 14或更低版本,则可以使用N
或char
代替uint8_t
; byte
更接近您想要的但是仅在C ++中可用17.如果您现在正在使用C ++ 14但可能会切换,我建议您在代码中放置byte
,然后在升级时将其切换出来)