“Default member initializer needed within definition of enclosing class outside of member functions” - is my code ill-formed?

前端 未结 5 1049
别那么骄傲
别那么骄傲 2020-12-05 02:50
#include 

struct foo
{
    int x{0};
    foo() noexcept = default;
    void f() noexcept(noexcept(std::declval())) {}
};

int main()
         


        
5条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-05 03:24

    As C++ 11 standard states

    § 5.3.7

    The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand (Clause 5), can throw an exception (15.1).

    noexcept-expression:
    noexcept ( expression )
    

    The result of the noexcept operator is a constant of type bool and is an rvalue. The result of the noexcept operator is false if in a potentially-evaluated context the expression would contain

    a potentially evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification (15.4), unless the call is a constant expression (5.19),

    — a potentially evaluated throw-expression (15.1),

    — a potentially evaluated dynamic_cast expression dynamic_cast(v), where T is a reference type, that requires a run-time check (5.2.7), or

    — a potentially evaluated typeid expression (5.2.8) applied to a glvalue expression whose type is a polymorphic class type (10.3).

    Otherwise, the result is true.

    and

    template 
    typename add_rvalue_reference::type declval() noexcept; // as unevaluated operand
    

    The add_rvalue_reference is of type Transformation Trait and, not explicitly said, but does not require object/function definition to be instantiated.

    From here it is clear that struct foo; ... noexcept(std::declval()) is a legal code. Where noexcept part, by the way, is equivalent to noexcept(true) that is equivalent to just noexcept, and noexcept(noexcept does not make sense, to get a constructor noexcept specifier you have to do this noexcept(foo()). The latter is valid as well, but, unfortunately, compilers are not able to deal with it, probably because of the order how they build the unit for non C++11 code, and they have not transformed this model yet. This reflects the nature of the bug that you encounter in the particular libc++ implementation. For some reasons add_rvalue_reference due to the presence of noexcept specifier tries to use declaration of the constructor and since that happens outside of the member function, as mentioned before, it fails. So yes, this is a bug of the library.

提交回复
热议问题