2017-10-05 55 views
2

我有一个CRTP模板类在这里:铛VS GCC CRTP:constexpr变量不能有非文字类

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

struct Derived : public Base<Derived> 
{ 
}; 

锵(5.0.0)不接受这一点:

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 

但海湾合作委员会(测试4.9.2和6.2)接受它就好了。

如何在叮当中这样做?

回答

2

Derived当您尝试在类模板Base中使用它时不是一个完整的类型,因此您不能以这种方式实际使用它。这是因为一个类型必须完整才能声明该类型的变量。没有办法解决它。
综上所述,类型在关闭}(以及与您的案例无关的其他例外情况,例如其成员函数内)完成。
这是标准的说什么(working draft):

一类被认为是在类说明符的关闭}完全定义的对象类型(或完整的类型)。
在类成员规范中,该类在函数体,默认参数,noexcept-说明符和默认成员初始化程序(包括嵌套类中的这些内容)中被认为是完整的。
否则它在自己的类成员规范中被认为是不完整的。

因此,铿锵是正确的,错误说或多或少相同。


正如在评论中提到的那样,存在一种解决方法。只要派生类型是(可以说)constexpr constructible,您可以在基类中定义一个constexpr函数,该函数返回您的未设置版本(无论它的意思)。

+0

谢谢:但是,如果我试图移植一个现有的代码库,它利用了GCC的这个“特性”来叮当,你的建议是什么? – Anton

+1

只要派生类型是constexpr可构造的,就可以在基类中定义一个constexpr函数,它返回它的_not set_版本(不管它是什么意思)。它可以为你工作吗? – skypjack

+0

是的,这是个好主意。谢谢。我会接受你的回答,但是你认为你也可以把你的评论放入答案中,作为后代吗? :-) – Anton