#include <type_traits>
template<class T>
auto f(T x) -> std::enable_if_t<x.size() == 4>;
is valid for Clang and MSVC, but invalid according to GCC. Which is correct? https://godbolt.org/z/q8v4G5vn6
Yes, the above code is well-formed and this is an instance of the GCC bug 80242 you have found.
x is type-dependent on T, and x.size() can be a constant expression for some x.
A compiler should never dismiss this code as ill-formed before instantiating f, because x.size() is possibly a constant expression.
Even if x is an object that doesn't exist at compile time, we can access its size:
std::array<int, 10> x;
constexpr std::size_t size = x.size();
... and all major compilers accept this, as they should.
The reason why this is okay to write is that .size() for std::array never accesses the value or address of the object x, only the template arguments that std::array was given.
This means that in your function, if T = std::array<...>, then x.size() is a constant expression and should be usable as a template argument for std::enable_if_t.
The error output for GCC is also totally nonsensical, which further reinforces the idea that this is a compiler bug:
<source>:5:46: error: template argument 1 is invalid
    5 | auto f(T x) -> std::enable_if_t<x.size() == 4>;
      |                                              ^
<source>:5:46: error: template argument 1 is invalid
<source>:5:46: error: template argument 1 is invalid
<source>:5:46: error: template argument 1 is invalid
<source>:5:46: error: template argument 1 is invalid
<source>:5:16: error: invalid use of template-name 'std::enable_if_t' without an argument list
    5 | auto f(T x) -> std::enable_if_t<x.size() == 4>;
      |                ^~~
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