【问题标题】:CRTP std::is_default_constructible not working as expectedCRTP std::is_default_constructible 未按预期工作
【发布时间】:2016-01-21 12:55:05
【问题描述】:
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_assert 移动到Base 的构造函数中,它可以正常工作

如果T 派生自Base,那么is_default_constructible&lt;T&gt; 在类级别总是为假的原因是什么?

Ideone

【问题讨论】:

    标签: c++ language-lawyer typetraits crtp


    【解决方案1】:

    Base&lt;X1&gt;X1的继承列表中被实例化时,X1是一个不完整的类型。这意味着X1在选中Class-Scope static_assert时,X1不是默认构造的。

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

    【讨论】:

      【解决方案2】:

      根据TartanLlama's answer,当TX 时,T 在类级别是不完整的。

      我想将此结果添加到 Undefined Behavior 中,因为 T 必须是 is_default_constructible 的完整类型:

      cppreference docs for is_default_constructible:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 2022-01-24
        • 2015-05-11
        • 2020-05-15
        相关资源
        最近更新 更多