C++ 为什么调用此constexpr静态成员函数时不将其视为constexpr?
为什么这个C++ 为什么调用此constexpr静态成员函数时不将其视为constexpr?,c++,constexpr,C++,Constexpr,为什么这个constepr静态成员函数由/]标识!Nah注释,在调用时不被视为constexpr struct Item_id { enum Enum { size, position, attributes, window_rect, max_window_size, _ }; static constexpr int n_items_ = _; // OK constexpr auto
constepr
静态成员函数由/]标识!Nah
注释,在调用时不被视为constexpr
struct Item_id
{
enum Enum
{
size, position, attributes, window_rect, max_window_size, _
};
static constexpr int n_items_ = _; // OK
constexpr auto member_n_items() const -> int { return _; } // OK
static constexpr auto static_n_items() -> int { return _; } // OK
static constexpr int so_far = n_items_; // OK
#ifndef OUT_OF_CLASS
static constexpr int bah = static_n_items(); //! Nah.
#endif
};
constexpr auto n_ids() -> int { return Item_id().member_n_items(); } // OK
auto main() -> int
{
#ifdef OUT_OF_CLASS
static constexpr int bah = Item_id::static_n_items(); // OK
#endif
}
mingwg++5.1报告
constexpr.cpp:12:46: error: 'static constexpr int Item_id::static_n_items()' called in a constant expression
static constexpr int bah = static_n_items(); //! Nah.
constexpr.cpp:12:46:错误:“static constexpr int Item_id::static_n_items()”在常量表达式中调用
static constexpr int bah=static_n_items();/!不。
Visual C++ 2015报告
constexpr.cpp(12): error C2131: expression did not evaluate to a constant
constexpr.cpp(12): note: failure was caused by call of undefined function or one not declared 'constexpr'
constexpr.cpp(12): note: see usage of 'Item_id::static_n_items'
constexpr.cpp(12):错误C2131:表达式的计算结果不是常数
constexpr.cpp(12):注意:失败是由调用未定义的函数或未声明为“constexpr”的函数引起的
constexpr.cpp(12):注意:请参阅“Item\u id::static\u n\u items”的用法
我的文本编辑器坚持调用中的名称与函数定义中的名称相同
它似乎与不完整的类有关,因为定义了OUT\u OF\u class
,它可以很好地编译
但是为什么n\u项
数据起作用,为什么这样的规则(对我来说没有意义)?从内存中,成员函数体只有在类被完全定义之后才被评估
static constexpr int bah = static_n_items();
构成类定义的一部分,但它引用的是一个(静态)成员函数,该函数尚未定义
解决方案:
将常量表达式延迟到基类并从基类派生
e、 g:
为什么你认为标准不允许它
因为这是非法的:
struct Item_id
{
// ... etc.
#ifndef OUT_OF_CLASS
static constexpr int bah;// = static_n_items(); //! Nah.
#endif
};
constexpr int Item_id::bah = static_n_items();
并且constexpr必须具有constexpr定义。我们唯一能定义它的地方是在它的声明期间
。。。因此,通过推论,它不能指的是身体尚未定义的任何功能
我不知道该在标准中寻找到哪里。可能有5个不同的、看似不相关的子句:)[class.mem]/2
在类成员规范中,类在函数体、默认参数、异常规范和默认成员初始值设定项(包括嵌套类中的此类内容)中被视为是完整的。否则,在其自身的类成员规范中,它被视为不完整的
在类的静态
数据成员的初始值设定项中,该类是不完整的。初始值设定项只能看到它前面的成员声明,它可以看到的任何成员函数都被视为已声明但未定义。对已声明但未定义的函数的调用不能是常量表达式。gcc6.1和clang3.8也不喜欢它。请注意,将bah
的声明和初始化移出struct
并执行static constexpr int bah=Item_id::static_n_items()代码>使其在G++5上编译。3@GillBates:谢谢,我也发现了同样的问题(见修改后的问题)。很奇怪,我想你可能是对的,谢谢!,但我一直认为重写(在类之后使用函数定义)只是一个概念工具。我记不起在《标准》中见过它。“那么,好吧,你知道标准的哪一部分规定了这一点吗?”Cheersandhth.-Alf三心二意的回答补充到了答案中。在漫长的一天结束后,我没有勇气去拖拽所有相关条款的标准。。。我相信你知道这种感觉!谢谢你把它挖出来![basic.scope.class]/1用稍微不同的语言说了几乎相同的事情,但我还没有找到一个引用来支持我的说法,即“它可以看到的任何成员函数都被认为是声明的,但没有定义的”。
struct Item_id
{
// ... etc.
#ifndef OUT_OF_CLASS
static constexpr int bah;// = static_n_items(); //! Nah.
#endif
};
constexpr int Item_id::bah = static_n_items();