CRTP std::is_default_constructible not working as expected

 ̄綄美尐妖づ 提交于 2019-12-14 03:49:57

问题


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
}

The static_assert at class level doesn't fire for any of the X classes. But kicks in for Y (which doesn't derive Base)

It works correctly if the static_assert is moved inside the constructor of Base

What is the reason that is_default_constructible<T> is always false at class level if T derives from Base?

Ideone


回答1:


When Base<X1> is instantiated in the inheritance list of X1, X1 is an incomplete type. This means that X1 is not default-constructible when the class-scope static_assert is checked.

The constructor for Base is only instantiated upon use, at which point X1 is now a complete type and is default-constructible. This is why the static_assert fires when inside the constructor, but not at class-scope.




回答2:


As per TartanLlama's answer, T is incomplete at class level when T is X.

I want to add this results in Undefined Behavior as T must be a complete type for is_default_constructible:

cppreference docs for is_default_constructible:

T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound. Otherwise, the behavior is undefined.



来源:https://stackoverflow.com/questions/34924432/crtp-stdis-default-constructible-not-working-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!