Note that a trailing-return-type is not mentioned in [class.mem]p6
A complete-class context of a class is a
(6.1) function body,
(6
Because you don't want it.
struct Test {
auto foo() -> decltype(bar());
auto bar() -> int;
auto baz() -> decltype(qux());
auto qux() -> decltype(baz());
};
Now you need all sorts of rules explaining which of the above is allowed and which is not.
So why does the standard places noexcept-specifier in complete-class context? Wouldn't it allow essentially the same thing in code like this:
struct Test {
void foo() noexcept(noexcept(bar()));
void bar() noexcept(noexcept(foo()));
};
?
It seems the standard doesn't address this well, and the compilers differ in treatment of this. Clang complains about the above code, but eats this:
struct Test {
void foo() noexcept(Test::b);
static const bool b = true;
};
GCC complains about the second code too, but accepts code with the member declarations swapped. It seems it doesn't treat the noexcept specifier as complete-class context at all.