CRTP std :: is_default_constructible无法按预期工作

时间:2016-01-21 12:55:05

标签: c++ language-lawyer typetraits crtp

template <class T>
class Base {
     static_assert(!std::is_default_constructible<T>::value,
                   "T must not be default constructible");
};

struct X1 : Base<X1> {};
struct X2 : Base<X2> {
   X2() = default;
};
struct X3 : Base<X3> {
   X3() {};
};
struct X4 : Base<X4> {
   X4() : Base{} {};
};

struct Y1 {};

int main() {
    // all compile. They shouldn't
    X1 x1; X2 x2; X3 x3; X4 x4; 
    // all compile. They shouldn't:
    Base<X1> bx1; Base<X2> bx2; Base<X3> bx3; Base<X4> bx4;  

    Base<Y1> by1; // static assert fires. This is the expected behavior
}

类级别的static_assert不会触发任何X类。但是要开始Y(不会导出Base

如果static_assertBase

的构造函数中移动,则它可以正常工作

如果is_default_constructible<T>来自T BaseActivity在课程级别始终为假,会导致错误的原因是什么?

Ideone

2 个答案:

答案 0 :(得分:3)

Base<X1>的继承列表中实例化X1时,X1是不完整的类型。这意味着,当检查类范围X1时,static_assert不是默认构造的。

Base的构造函数仅在使用时被实例化,此时X1现在是完整类型并且是可默认构造的。这就是static_assert在构造函数内部而不是在类范围内触发的原因。

答案 1 :(得分:0)

根据TartanLlama's answer,当TT时,X在课程级别上不完整。

我想在未定义的行为中添加此结果,因为T必须是is_default_constructible的完整类型:

cppreference docs for is_default_constructible

  

T应为完整类型,(可能是cv限定的)void或数组   未知界限否则,行为未定义。