Consider the following class:
struct S {
template<typename T>
std::enable_if_t<std::is_void<T>::value>
f() noexcept {}
template<typename T>
std::enable_if_t<not std::is_void<T>::value>
g() noexcept {}
};
As expected, this compiles:
s.f<void>();
This one does not instead:
s.g<void>();
What puzzles me is that the following main
compiles with GCC (6.2) and doesn't compile with clang (3.9):
int main() {
static_assert(noexcept(&S::f<void>), "!");
static_assert(noexcept(&S::g<void>), "!");
}
I would have said the second assert failed because of the invalid specialization. The two compilers disagree on that.
Which one is correct?
[except.spec]/13:
The set of potential exceptions of an expression
e
is empty ife
is a core constant expression (5.20).
That is, GCC does not even resolve the template-id, because it knows from the get-go that the result is true
(since g<void>
is not a static data member template specialization whose type has an overloaded operator&
). While being clever, the behavior is non-conforming, because any occurrence of a template-id entails the substitution of the arguments into the declaration of the function template.
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