#include <utility> struct foo { int x{0}; foo() noexcept = default; void f() noexcept(noexcept(std::declval<foo&>())) {} }; int main() { }
live example on godbolt
The code above compiles with any version of g++ I tested, and with clang++ from 3.6 to 3.9.1, but does not compile with clang++ 4.0.0:
test.cpp:6:5: error: default member initializer for 'x' needed within definition of enclosing class 'foo' outside of member functions foo() noexcept = default; ^ type_traits:126:26: note: in instantiation of template class 'std::is_function<foo &>' requested here : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type ^ type_traits:154:39: note: in instantiation of template class 'std::__or_<std::is_function<foo &>, std::is_reference<foo &>, std::is_void<foo &> >' requested here : public integral_constant<bool, !_Pp::value> ^ type_traits:598:14: note: in instantiation of template class 'std::__not_<std::__or_<std::is_function<foo &>, std::is_reference<foo &>, std::is_void<foo &> > >' requested here : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>, ^ type_traits:121:26: note: in instantiation of template class 'std::is_object<foo &>' requested here : public conditional<_B1::value, _B1, _B2>::type ^ type_traits:635:14: note: in instantiation of template class 'std::__or_<std::is_object<foo &>, std::is_reference<foo &> >' requested here : public __or_<is_object<_Tp>, is_reference<_Tp>>::type ^ type_traits:1667:33: note: in instantiation of template class 'std::__is_referenceable<foo &>' requested here template<typename _Tp, bool = __is_referenceable<_Tp>::value> ^ type_traits:1678:14: note: in instantiation of default argument for '__add_rvalue_reference_helper<foo &>' required here : public __add_rvalue_reference_helper<_Tp> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type_traits:2267:12: note: in instantiation of template class 'std::add_rvalue_reference<foo &>' requested here inline typename add_rvalue_reference<_Tp>::type ^ wtfff.cpp:7:32: note: while substituting explicitly-specified template arguments into function template 'declval' void f() noexcept(noexcept(std::declval<foo&>())) {} ^ wtfff.cpp:5:9: note: default member initializer declared here int x{0}; ^
Is my code ill-formed? If so, what's the meaning of the error?
Note that removing the noexcept
from the constructor or the {0}
initializer from x
will make the code compile.
Your code is fine from what I can tell. Clang seems to struggle with the = default
constructor rather than just defining a default constructor manually. It has the following spiel in its source code about it:
DR1351: If the brace-or-equal-initializer of a non-static data member invokes a defaulted default constructor of its class or of an enclosing class in a potentially evaluated subexpression, the program is ill-formed.
This resolution is unworkable: the exception specification of the default constructor can be needed in an unevaluated context, in particular, in the operand of a noexcept-expression, and we can be unable to compute an exception specification for an enclosed class.
Any attempt to resolve the exception specification of a defaulted default constructor before the initializer is lexically complete will ultimately come here at which point we can diagnose it.
I think it may be incorrectly picking up the error, personally. But it specifially mentions "defaulted default constructor".
The following seems to work:
#include <utility> struct foo { int x{0}; foo() noexcept {} // = default; void f() noexcept(noexcept(std::declval<foo&>())) {} }; int main() { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With