#include
struct foo
{
int x{0};
foo() noexcept = default;
void f() noexcept(noexcept(std::declval())) {}
};
int main()
As C++ 11 standard states
§ 5.3.7
The
noexceptoperator 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
templatetypename 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.