Why is this constexpr static member function not seen as constexpr when called?

前端 未结 2 1732
猫巷女王i
猫巷女王i 2020-12-11 00:44

Why is this constexpr static member function, identified by the //! Nah comment, not seen as constexpr when called?

相关标签:
2条回答
  • 2020-12-11 01:18

    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 :)

    0 讨论(0)
  • 2020-12-11 01:22

    [class.mem]/2

    Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

    In the initializer of a static data member of a class, the class is incomplete. The initializer can only see the declarations of members which precede it, and any member functions it can see are considered declared but not defined. A call to a function that is declared but not defined can not be a constant expression.

    0 讨论(0)
提交回复
热议问题