gez*_*eza 17 c++ language-lawyer c++17
看看这段代码:
struct NonConstexpr {
NonConstexpr() { }
};
template <typename T>
struct Bar {
NonConstexpr nonConstexpr;
constexpr Bar() { }
};
struct Foo {
Bar<void> bar;
constexpr Foo() { }
};
Run Code Online (Sandbox Code Playgroud)
Foo有一个成员,Foo::bar::nonConstexpr有一个非constexpr构造函数.所以,我的期望是这不应该编译.但它与gcc,clang和msvc编译.这是编译器错误,还是某些规则允许编译此代码?
如果我直接添加NonConstexpr成员Foo,代码将不再编译.
(我遇到了这个问题,因为我期望全局Foo对象的静态初始化,但它被动态初始化,并且由于"静态初始化命令惨败"而导致问题)
P.W*_*P.W 10
这是编译器错误,还是某些规则允许编译此代码?
允许这个编译的规则是:
10.1.5 constexpr指定程序[dcl.constexpr]
...
6.如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,那么该特化仍然是一个constexpr函数或者constexpr构造函数,即使对这样的函数的调用不能出现在常量表达式中.如果在被视为非模板函数或构造函数时模板的特化不满足constexpr函数或constexpr构造函数的要求,则模板格式错误,无需诊断.
以上引用来自CPP标准草案N4713.
从引用中可能不清楚Bar<void>构造函数如何Foo作为构造函数出现在构造Foo函数中constexpr.但正如评论中所指出的,constexpr与常量表达式不同.Foo构造函数不是表达式,更不是常量表达式.