从模板参数到构造函数参数
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
.
您可以制作 bitset32
和 bitset64
模板,例如
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>> );
}
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
.
您可以制作 bitset32
和 bitset64
模板,例如
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>> );
}