我有一个包含两个构造函数的类模板,一个构造函数采用无符号类型,另一个构造函数对其自身进行常量引用,这两个构造函数在构造类时具有相同的行为。
在构造此类时,有3种情况,这取决于其类型的大小和要传入的类型。我还希望通过类构造函数的初始化列表来初始化成员。
该类看起来像这样:
template<typename T>
struct Foo {
T data;
template<typename P>
Foo( const P val, const unsigned char c ) :
data { static_cast<T>( val /* some operation done to val based on each case*/ ) } {
assert( /* based on cases above,
and each case has its own conditions to assert */ );
}
template<typename P>
Foo( const Foo<P>& f, const unsigned char c ) :
data{ static_cast<T>( Foo.val /* some operation done to val based on each case*/ ) } {
assert( /* based on cases above,
and each case has its own conditions to assert */ );
};
这3种情况如下:
case 1: if( sizeof(P) > sizeof(T) ) construct Foo<T> with these conditions, initialize member data in this specific way and assert accordingly case 2: if( sizeof(T) > sizeof(P) ) construct Foo<T> with these conditions, initialize member data in this specific way and assert accordingly case 3: if ( sizeof(T) == sizeof(P) ) construct Foo<T> with these conditions, initialize member data in this specific way and assert accordingly
有没有简单的方法可以做到这一点?请记住,该成员是通过构造函数的初始值设定项列表进行初始化的,但是根据上述3种情况,将以不同的方式初始化数据成员。
我不知道该如何处理。这里的所有信息都应该在编译时可用,所以我不明白为什么会有问题,但是我不知道如何设置构造函数以具有此功能。而且甚至可以做到吗?
编辑
有关类型T
和P
的背景知识:T
和P
均是以下任意一项:
类型:以字节为单位的大小:以位为单位的大小:
std::uint8_t
1字节8位std::uint16_t
2字节16位std::uint32_t
4字节32位std::uint64_t
8字节64位
一旦我们根据两个大小的比较定义了3个条件,则断言的工作方式如下:传入的无符号char也是断言中条件的一部分,并且它具有一定范围的值是。这是一个表格:我将用idx
表示的未签名字符。
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
if ( sizeof(P) > sizeof(T) )
// comparision formula:
// idx <= (((sizeof(P) / sizeof(T)) - 1)
// Foo<T = u8> From: Foo<P = u16> idx[0,1], Foo<P =u32> idx[0,3], Foo<P = u64> idx[0,7]
// Foo<T = u16> From: Foo<P = u32> idx[0,1], Foo<P = u64> idx[0,3]
// Foo<T = u32> From: Foo<P = u64> idx[0,1]
if ( sizeof(T) > sizeof(P) )
// comparision formula:
// idx <= (((sizeof(T) / sizeof(P)) - 1)
// Foo<T = u16> From: Foo<P = u8> idx[0,1]
// Foo<T = u32> From: Foo<P = u8> idx[0,4], Foo<P = u16> idx[0,1]
// Foo<T = u64> From: Foo<P = u8> idx[0,7], Foo<P = u16> idx[0,3], Foo<P = u32> idx[0,1]
if ( sizeof(P) == sizeof(T) ) {
// no conditional checks
// no assertion
// in this case idx is not used and is not a part of any calculation
// the two sizes match so it's just a normal initialization.
答案 0 :(得分:3)
在这种情况下,无法使用if constexpr
,而您不得不依靠SFINAE。首先,将构造从Foo<P>
构造函数委托给P
构造函数:
template<typename P>
Foo(const Foo<P>& f, const unsigned char c) : Foo(f.val, c) {}
P
构造函数只需要具有三种选择,根据P
的大小,是否启用了其中一种:
template<typename P, std::enable_if_t<(sizeof(P) > sizeof(T))>* = nullptr>
Foo(P val, const unsigned char c) : data(...) {}
template<typename P, std::enable_if_t<sizeof(P) == sizeof(T)>* = nullptr>
Foo(P val, const unsigned char c) : data(...) {}
template<typename P, std::enable_if_t<(sizeof(P) < sizeof(T))>* = nullptr>
Foo(P val, const unsigned char c) : data(...) {}
如果希望P
构造函数具有相同的断言,而不管P
的大小如何,也可以添加一个额外的委派层。