这是一个错误吗? Constexpr构造函数无声地变为非constexpr [英] Is this a bug? Constexpr constructor silently becomes non-constexpr

查看:100
本文介绍了这是一个错误吗? Constexpr构造函数无声地变为非constexpr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看下面的代码:

struct NonConstexpr {
    NonConstexpr() { }
};

template <typename T>
struct Bar {
    NonConstexpr nonConstexpr;

    constexpr Bar() { }
};

struct Foo {
    Bar<void> bar;

    constexpr Foo() { }
};

Foo具有成员Foo::bar::nonConstexpr,该成员具有非constexpr构造函数.因此,我期望它不应该编译.但是它可以使用gcc,clang和msvc进行编译.这是编译器错误,还是某些规则允许该代码进行编译?

Foo has a member, Foo::bar::nonConstexpr, which has a non-constexpr constructor. So, my expectation is that this should not compile. But it compiles with gcc, clang and msvc. Is this a compiler bug, or some rule allows this code to compile?

如果我直接将NonConstexpr成员添加到Foo中,则代码将不再编译.

If I add a NonConstexpr member into Foo directly, the code doesn't compile anymore.

(我遇到了这个问题,因为我期望对全局Foo对象进行静态初始化,但是由于静态初始化顺序失败",所以它进行了动态初始化,并引起了问题)

(I got this problem, because I've expected static initialization for a global Foo object, but it got dynamically initialized, and it caused a problem, because of "static initialization order fiasco")

推荐答案

这是编译器错误,还是某些规则允许此代码进行编译?

Is this a compiler bug, or some rule allows this code to compile?

允许编译的规则是:

10.1.5 constexpr规范[dcl.constexpr]
...
6.如果constexpr函数模板或类模板的成员函数的实例化模板专业化不能满足constexpr函数或constexpr构造函数的要求,则该专业化仍然是constexpr函数或constexpr构造函数,即使对此类函数的调用不能出现在常量表达式中.如果当模板被认为是非模板函数或构造函数时,如果模板的专业化不能满足constexpr函数或constexpr构造函数的要求,则模板格式错误,无需诊断.

10.1.5 The constexpr specifier [dcl.constexpr]
...
6. If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is still a constexpr function or constexpr constructor, even though a call to such a function cannot appear in a constant expression. If no specialization of the template would satisfy the requirements for a constexpr function or constexpr constructor when considered as a non-template function or constructor, the template is ill-formed, no diagnostic required.

以上引用来自CPP标准草案N4713.

The above quote is taken from CPP standard draft N4713.

从引号中可能还不清楚,因为Foo的构造函数是constexprBar<void>的构造函数如何出现在Foo的构造函数中.但是如注释中所述,constexpr与常量表达式不同. Foo的构造函数不是表达式,更不用说常量表达式.

From the quote it may not be clear how Bar<void>'s constructor can appear in Foo's constructor as Foo's constructor is constexpr. But as noted in the comments, constexpr is not the same as constant expression. Foo's constructor is is not an expression, much less a constant expression.

这篇关于这是一个错误吗? Constexpr构造函数无声地变为非constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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