[英]C++ Array type dependent on template type
我有一個具有不可分割的模板參數N
。
template<unsigned int N>
class test {
}
現在,我想擁有一個std::vector
,其整數類型應盡可能小以容納N
位。
例如
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
還有更好的方法嗎?
使用條件呢?
#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
}
或者,以更優雅的方式(IMHO),您可以定義類型特征(在下面的示例中為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
}
根據對問題的評論,您實際上不需要內置類型。 任何可復制的可移動對象都可以放入向量中。
如果您只想對數據進行排序,則建議使用std::bitset<2*N>
或std::array<std::byte, (2*N+7)/8>
(或std::array<std::byte, (2*N+CHAR_BIT-1)/CHAR_BIT>
如果您在怪異的系統上運行),帶有自定義“ Compare
進行排序。 如果您有其他用途(您可能會這樣做),我建議您使用一個自定義類作為其基礎存儲; 這使您可以添加更多功能,例如獲得特定基礎。
在大多數系統上,如果N
是32或64的倍數(取決於實現),則std::bitset
將沒有開銷,但這不能保證。 通常,字節數組的開銷不會超過C ++的開銷。 如有必要,這兩種方法都可以擴展到64位以上,並且字節數組的空間開銷最小,甚至比使用整數類型還要少,因為它不會強制大小為2的冪。 在這兩個方法之上添加自定義類根本不會增加任何開銷。
(如果您使用的是C ++ 14或更低版本,則可以使用char
或uint8_t
代替byte
;一個byte
更接近您想要的byte
,但是僅在C ++ 17中可用。如果您現在使用的是C ++ 14,但是可能會切換,建議您在代碼中using byte = uint8_t
,然后在升級時將其切換出來)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.