问题描述
为什么此 constexpr
static
成员函数由 //标识! Nah
评论,被调用时不被视为 constexpr
?
Why is this constexpr
static
member function, identified by the //! Nah
comment, not seen as constexpr
when called?
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
}
MinGW g ++ 5.1报告
MinGW g++ 5.1 reports
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.
Visual C ++ 2015报告
Visual C++ 2015 reports
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'
我的文本编辑器坚持要求调用中的名称相同
My text editor insists that the name in the call is the same as the name in the function definition.
它似乎与不完整的类有关,因为与 OUT_OF_CLASS
定义它可以很好地编译。
It appears to have something to do with incomplete class, because with OUT_OF_CLASS
defined it compiles nicely.
但是为什么 n_items _
数据起作用,为什么这样的规则(确实
But then why does the n_items_
data work, and, why such a rule (doesn't make sense to me)?
推荐答案
从内存中,仅在完全定义了类之后,才对成员函数主体进行求值。
From memory, member function bodies are evaluated only once the class has been completely defined.
static constexpr int bah = static_n_items();
构成类定义的一部分,但它引用的是(静态)成员函数,尚不能
forms part of the class definition, but it's referring to a (static) member function, which cannot yet be defined.
解决方案:
将常量表达式推迟为基类并从中派生。
defer constant expressions to a base class and derive from it.
例如:
struct Item_id_base
{
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
};
struct Item_id : Item_id_base
{
#ifndef OUT_OF_CLASS
static constexpr int bah = static_n_items(); // now OK
#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
}
因为这是非法的:
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定义。
And a constexpr must have a constexpr definition. The only place we can define it is during its declaration...
...所以我们唯一可以定义它的地方是……所以通过推论,它不能引用尚未定义身体的任何函数。
... so by deduction it cannot refer to any function who's body is not yet defined.
我不知所措要知道所有标准在哪里。可能有5个不同的,看似无关的子句:)
I am at a loss to know where to look in the standard for all that. Probably 5 different, seemingly unrelated clauses :)
这篇关于为什么在调用此constexpr静态成员函数时不将其视为constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!