clang vs gcc CRTP:constexpr变量不能有非文字类型 [英] clang vs gcc CRTP: constexpr variable cannot have non-literal type

查看:826
本文介绍了clang vs gcc CRTP:constexpr变量不能有非文字类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

结构派生:public Base< Derived>
{
};

铿锵(5.0.0)不接受:

  5:< source>:5:24:error:constexpr变量不能有非文字类型'const Derived'
constexpr static S NOT_SET {0} ;

8:< source>:8:25:注意:在这里请求的模板类'Base< Derived>'的实例中
struct Derived:public Base< Derived>

5:< source>:5:24:注意:不完整类型'const Derived'不是字面类型
constexpr static S NOT_SET {0};
$
8:< source>:8:8:注意:'Derived'的定义直到关闭'}'
struct Derived:public Base< Derived>
^
1产生的错误。
编译器退出,结果代码为1

但是gcc(在4.9.2和6.2上测试)接受它就好。



在clang中如何做这件事?

解决方案

当您尝试在类模板 Base 中使用它时,派生的不是完整的类型,所以你不能以这种方式实际使用它。这是因为一个类型必须完整才能声明该类型的变量。没有办法解决它。

综上所述,类型在结尾} 处是完整的(以及其他与您的情况无关的异常,就像在它的成员函数中一样)。
这就是标准所说的( working draft ):


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

因此,clang是正确的,这个错误说明或多或少是相同的。






正如评论中提到的那样,解决这个问题的方法是存在的。只要派生类型是(让我说)可构造,您可以在基类中定义一个constexpr函数,它返回它的 not set 版本(不管它是什么意思)。


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?

解决方案

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).

这篇关于clang vs gcc CRTP:constexpr变量不能有非文字类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆