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.
Solution:
defer constant expressions to a base class and derive from it.
e.g.:
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
}
Why do you think the standard disallows it?
Because this is illegal:
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();
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.
I am at a loss to know where to look in the standard for all that. Probably 5 different, seemingly unrelated clauses :)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…