I recently upgraded GCC to 8.2, and most of my SFINAE expressions have stopped working.
The following is somewhat simplified, but demonstrates the problem:
#include <iostream>
#include <type_traits>
class Class {
public:
template <
typename U,
typename std::enable_if<
std::is_const<typename std::remove_reference<U>::type>::value, int
>::type...
>
void test() {
std::cout << "Constant" << std::endl;
}
template <
typename U,
typename std::enable_if<
!std::is_const<typename std::remove_reference<U>::type>::value, int
>::type...
>
void test() {
std::cout << "Mutable" << std::endl;
}
};
int main() {
Class c;
c.test<int &>();
c.test<int const &>();
return 0;
}
C++ (gcc) – Try It Online
C++ (clang) – Try It Online
Older versions of GCC (unfortunately I don't remember the exact version I had installed previously) as well as Clang compile the above code just fine, but GCC 8.2 gives an error stating:
: In function 'int main()':
:29:19: error: call of overloaded 'test()' is ambiguous
c.test();
^
:12:10: note: candidate: 'void Class::test() [with U = int&; typename std::enable_if::type>::value>::type ... = {}]'
void test() {
^~~~
:22:10: note: candidate: 'void Class::test() [with U = int&; typename std::enable_if::type>::value)>::type ... = {}]'
void test() {
^~~~
:30:25: error: call of overloaded 'test()' is ambiguous
c.test();
^
:12:10: note: candidate: 'void Class::test() [with U = const int&; typename std::enable_if::type>::value>::type ... = {}]'
void test() {
^~~~
:22:10: note: candidate: 'void Class::test() [with U = const int&; typename std::enable_if::type>::value)>::type ... = {}]'
void test() {
As is usually the case when different compilers and compiler versions handle the same code differently I assume I am invoking undefined behavior. What does the standard have to say about the above code? What am I doing wrong?
Note: The question is not for ways to fix this, there are several that come to mind. The question is why this doesn't work with GCC 8 - is it undefined by the standard, or is it a compiler bug?
Note 2: Since everyone was jumping on the default void
type of std::enable_if
, I've changed the question to use int
instead. The problem remains.
Note 3: GCC bug report created
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…