C++ 这是虫子吗?Constexpr构造函数以静默方式变为非Constexpr
请看以下代码:C++ 这是虫子吗?Constexpr构造函数以静默方式变为非Constexpr,c++,language-lawyer,c++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() { } }; struct unconstexpr{ 非结构化x
struct NonConstexpr {
NonConstexpr() { }
};
template <typename T>
struct Bar {
NonConstexpr nonConstexpr;
constexpr Bar() { }
};
struct Foo {
Bar<void> bar;
constexpr Foo() { }
};
struct unconstexpr{
非结构化xpr(){}
};
模板
结构条{
非stexpr非stexpr;
constexpr Bar(){}
};
结构Foo{
酒吧;
constexpr Foo(){}
};
Foo
有一个成员,Foo::bar::nonConstexpr
,它有一个非constexpr构造函数。因此,我的期望是,这不应该编译。但它是用gcc、clang和msvc编译的。这是一个编译器错误,还是某些规则允许编译此代码
如果我直接在Foo
中添加一个noncostexpr
成员,代码就不会再编译了
(我遇到了这个问题,因为我期望对全局Foo
对象进行静态初始化,但它得到了动态初始化,并导致了一个问题,因为“静态初始化顺序失败”)
这是一个编译器错误,还是某些规则允许编译此代码
允许进行编译的规则是:
10.1.5 constexpr规范[dcl.constexpr]…
6.如果
constepr
函数模板或类模板的成员函数的实例化模板专门化不能满足constepr
函数或constepr
构造函数的要求,则该专门化仍然是constepr
函数或constepr
构造函数,即使对此类函数的调用不能出现在常量表达式中。如果模板的专门化不能满足constepr
函数或constepr
构造函数(当被视为非模板函数或构造函数时)的要求,则模板格式不正确,无需诊断
上述报价摘自CPP标准草案N4713
从引文中可能不清楚
Bar
的构造函数如何出现在Foo
的构造函数中,因为Foo
的构造函数是constepr
。但正如注释中所指出的,constexpr
与常量表达式不同Foo
的构造函数不是一个表达式,更不用说是一个常量表达式。允许它编译,但模板是格式错误的NDR。有趣,“即使对这样一个函数的调用不能出现在常量表达式中”。这是否意味着Bar
的构造函数不能出现在Foo
的构造函数中(Foo
的构造函数是constexpr,而Bar
的构造函数不是,所以它不能出现)?@geza-构造函数是constexpr,但不是常量表达式(根本不是表达式)。@geza:同意讲故事者的解释。构造器不是一个表达式。@StoryTeller:好的,谢谢,读了几遍这句话,再加上你的评论,现在我明白发生了什么。但是,现在我无法理解这背后的逻辑:“无法满足……constexpr构造函数的要求,这个专门化仍然是……constexpr构造函数”。什么?为什么?如果Bar
不是模板,GCC不会编译此代码。或许,一个相关的问题: