C++ 初始化类模板';根据不同的条件选择不同的成员
我有一个类模板,它有两个构造函数,一个采用无符号类型,另一个采用自身的常量引用,两个构造函数在构造类时具有相同的行为 关于如何构造此类,有3种情况,这取决于类型的大小和传入的类型。我还希望通过类构造函数的初始值设定项列表初始化成员 这个类看起来像这样:C++ 初始化类模板';根据不同的条件选择不同的成员,c++,templates,constructor,c++17,list-initialization,C++,Templates,Constructor,C++17,List Initialization,我有一个类模板,它有两个构造函数,一个采用无符号类型,另一个采用自身的常量引用,两个构造函数在构造类时具有相同的行为 关于如何构造此类,有3种情况,这取决于类型的大小和传入的类型。我还希望通过类构造函数的初始值设定项列表初始化成员 这个类看起来像这样: template<typename T> struct Foo { T data; template<typename P> Foo( const P val, const unsigned ch
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 */ );
};
在这种情况下,如果不能使用constexpr,则必须使用SFINAE。首先,将构造从
Foo
构造函数委托给P
构造函数:
template<typename P>
Foo(const Foo<P>& f, const unsigned char c) : Foo(f.val, c) {}
如果您希望
p
构造函数具有相同的断言,而不管p
的大小,您也可以添加额外的委托层。我将编辑上面关于断言如何工作的问题。我完成了编辑,以提供有关如何执行构造的更多信息。不过,我想我已经开始了解或查看SFINAE的模式,以及如何使用std::enable_(如果_t
)。我创建了一个虚拟类来复制您在上面所做的操作,我收到了Visual Studio 2017编译器错误C2059:语法错误:sizeof
我想我现在已经完成了这个shell,我还没有做任何测试。有一次,我在一个简单的案例中测试了这一点;我应该能够把它融入我的实际课堂。
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.
template<typename P>
Foo(const Foo<P>& f, const unsigned char c) : Foo(f.val, c) {}
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(...) {}