Consider this program:
#include <type_traits>
template <typename T> constexpr bool g() { return true; }
template <typename T> std::enable_if_t< g<T>()> f() {}
template <typename T> std::enable_if_t<!g<T>()> f() {}
int main() { f<int>(); }
(Compiler Explorer)
It is acceptable to various versions of GCC and Clang, but it is not acceptable to MSVC, which fails to compile with the error message
1>D:\x.cpp(5,49): error C2995: 'enable_if<0,void>::type f(void)': function template has already been defined
1>D:\x.cpp(4): message : see declaration of 'f'
1>D:\x.cpp(4,49): error C3861: 'f': identifier not found
The first error message suggests an ODR violation to me - but if this program is ill-formed NDR, I need help understanding why that is so. I've checked [temp.over.link] in the standard draft, but I'm not confident that I'm interpreting it correctly. To my understanding the program is okay because these function templates have differing signatures.
In the unlikely case this program is correct, why does MSVC reject it?
MSVC has a bug here.
For most functions, equivalence of arguments is sufficient to indicate an error. For templates, the return type expression is also involved.
MSVC seems to be ignoring the return type expression, and generating an error as if it could ignore it.
The g<T>()
/!g<T>()
part could be split into sizeof(T)==1
and sizeof(T)!=1
to remove one other confounding feature (the fact that one of those two cannot in practice be instantiated).
Try this:
template <typename T, std::enable_if_t<g<T>(),bool> =true> void f() {}
template <typename T, std::enable_if_t<!g<T>(),bool> =true> void f() {}
it will work in all 3 compilers.
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