简体   繁体   中英

Does this program violate the ODR?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM