簡體   English   中英

C ++數組類型取決於模板類型

[英]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=1N=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或更低版本,則可以使用charuint8_t代替byte ;一個byte更接近您想要的byte ,但是僅在C ++ 17中可用。如果您現在使用的是C ++ 14,但是可能會切換,建議您在代碼中using byte = uint8_t ,然后在升級時將其切換出來)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM