clang vs gcc CRTP: constexpr variable cannot have non-literal type

亡梦爱人 提交于 2019-12-12 09:46:32

问题


I have a CRTP template class here:

template <typename S>
class Base
{
    public:
    constexpr static S NOT_SET{0};
};

struct Derived : public Base<Derived>
{
};

Clang (5.0.0) does not accept this:

5 : <source>:5:24: error: constexpr variable cannot have non-literal type 'const Derived'
    constexpr static S NOT_SET{0};
                       ^
8 : <source>:8:25: note: in instantiation of template class 'Base<Derived>' requested here
struct Derived : public Base<Derived>
                        ^
5 : <source>:5:24: note: incomplete type 'const Derived' is not a literal type
    constexpr static S NOT_SET{0};
                       ^
8 : <source>:8:8: note: definition of 'Derived' is not complete until the closing '}'
struct Derived : public Base<Derived>
       ^
1 error generated.
Compiler exited with result code 1

But gcc (tested on 4.9.2 and 6.2) accepts it just fine.

How does one go about doing this in clang?


回答1:


Derived isn't a complete type when you try to use it in the class template Base, so you cannot actually use it that way. That's because a type must be complete to be able to declare a variable of that type. No way to work around it.
To sum up, a type is complete at the closing } (and other exceptions that are irrelevant for your case, like within its member functions).
This is what the standard says (working draft):

A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier.
Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes).
Otherwise it is regarded as incomplete within its own class member-specification.

Therefore clang is right and the error says more or less the same.


As mentioned in the comments, a way to work around it exists. As long as the derived type is (let me say) constexpr constructible, you can define a constexpr function in the base class that returns you its not set version (whatever it means).



来源:https://stackoverflow.com/questions/46576847/clang-vs-gcc-crtp-constexpr-variable-cannot-have-non-literal-type

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