从模板参数到构造函数参数

From template parameter to constructor argument

C++17(或更早但不是 c++20)是否允许这样做?

我需要一个 type_traited 条件 class,就像一个带有内部 32 位或 64 位无符号整数存储的位集,这取决于模板参数 N 是小于 32 还是更大(请忘记更多超过 64 位)。

但约束是最终为所有可能的情况实现两个且仅两个 classes。下一个源代码使用静态和 运行 时间断言定义问题:

科里鲁 link: http://coliru.stacked-crooked.com/a/d53a5b00bd828fb5

#include <cassert>
#include <iostream>
#include <type_traits>

struct bitset32
{
    bitset32() : bits(0) { }
    bitset32(int _bits) : bits(_bits) { }

    const int bits;
    uint32_t value;
};

struct bitset64
{
    bitset64() : bits(0) { }
    bitset64(int _bits) : bits(_bits) { }
    
    const int bits;
    uint64_t value;
};

template <int N>
using bitset = std::conditional_t<(N<=32), bitset32, bitset64>;

int main ()
{
    static_assert(std::is_same<bitset<1>, bitset<2>>::value);
    static_assert(std::is_same<bitset<33>, bitset<34>>::value);
    static_assert(!std::is_same<bitset<1>, bitset<33>>::value);

    bitset<1> var1;
    bitset<15> var2;
    bitset<32> var3;
    bitset<64> var4;

    assert(var1.bits == 1);
    assert(var2.bits == 15);
    assert(var3.bits == 32);
    assert(var4.bits == 64);
}

欢迎任何解决方案,即使它改变了基本类型并使用继承或任何其他必要的机制,但请不要提供使用模板函数返回 template<int N> make_bitset { return Bitset<N>(N); } 样式的对象,因为它是需要使用此构造实现变量 Bitset<N> variable_name.

您可以制作 bitset32bitset64 模板,例如

template <std::size_t BitsUsed>
struct bitset32
{
    bitset32() : bits(BitsUsed) { }
    bitset32(int _bits) : bits(_bits) { }

    const int bits;
    uint32_t value;
};

template <std::size_t BitsUsed>
struct bitset64
{
    bitset64() : bits(BitsUsed) { }
    bitset64(int _bits) : bits(_bits) { }
    
    const int bits;
    uint64_t value;
};

现在默认构造函数将引入正确的位数。然后你只需要修改你的别名就像

template <int N>
using bitset = std::conditional_t<(N<=32), bitset32<N>, bitset64<N>>;

你得到了你想要的行为。

如果您想将 bitset<5> 存储在与 bitset<32> 相同的容器中,这将不起作用,因为不同的模板实例化会创建不同的类型。

一个新假设,CTAD 基于

#include <cstdint>
#include <iostream>
#include <type_traits>

template <std::size_t>
struct BitSet;

template <>
struct BitSet<32u>
 {
   template <typename ... Ts>
   BitSet (Ts...) {}

   std::uint32_t value;
 };

template <>
struct BitSet<64u>
 {
   template <typename ... Ts>
   BitSet (Ts...) {}

   std::uint64_t value;
 };

template <typename ... Ts>
BitSet (Ts...) -> BitSet<(32 < sizeof...(Ts) ? 64u : 32u)>;


int main()
 {
   auto b1 = BitSet{1};
   auto b2 = BitSet{2};
   auto b3 = BitSet{0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
                    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
                    30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
   auto b4 = BitSet{0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
                    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
                    30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
                    40, 41, 42, 43, 44, 45, 46, 47, 48, 49};

   static_assert( std::is_same_v<decltype(b1), decltype(b2)> );
   static_assert( std::is_same_v<decltype(b1), BitSet<32u>> );
   static_assert( std::is_same_v<decltype(b3), decltype(b4)> );
   static_assert( std::is_same_v<decltype(b3), BitSet<64u>> );
 }