这是错误吗? Constexpr构造函数无声地变为非constexpr

时间:2018-12-05 11:05:25

标签: c++ language-lawyer c++17

看下面的代码:

do {
    try storeCoordinates(actualRouteInUseCoordinatesArray)
} catch { print(error) }

struct NonConstexpr { NonConstexpr() { } }; template <typename T> struct Bar { NonConstexpr nonConstexpr; constexpr Bar() { } }; struct Foo { Bar<void> bar; constexpr Foo() { } }; 具有成员Foo,该成员具有非constexpr构造函数。因此,我期望它不应该编译。但是它可以使用gcc,clang和msvc进行编译。这是编译器错误,还是某些规则允许该代码编译?

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

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

1 个答案:

答案 0 :(得分:10)

  

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

允许编译的规则是:

  

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

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


从引语中可能还不清楚,Bar<void>的构造函数是Foo时,Foo的构造函数如何出现在constexpr的构造函数中。但是,如注释中所述,constexpr与常量表达式不同。 Foo的构造函数不是表达式,更不是常量表达式。