Недавно я обновил GCC до 8.2, и большинство моих выражений SFINAE перестали работать.
Следующее несколько упрощено, но демонстрирует проблему:
#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++ (clang) - Попробуйте онлайн
Старые версии GCC (к сожалению, я не помню точной версии, которую я установил ранее), а также Clang компилирует приведенный выше код просто отлично, но GCC 8.2 дает сообщение об ошибке:
: 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() {
Как обычно бывает, когда разные компиляторы и версии компилятора обрабатывают один и тот же код по-разному, я предполагаю, что я вызываю неопределенное поведение. Что должен сказать стандарт о вышеуказанном коде? Что я делаю не так?
Примечание. Вопрос не в том, как это исправить, есть несколько, которые приходят на ум. Вопрос в том, почему это не работает с GCC 8 - не определено ли оно стандартом или это ошибка компилятора?
Примечание 2: Поскольку все были прыгали по умолчанию void
типа std::enable_if
, я изменил вопрос на использование int
вместо этого. Проблема остается.
Примечание 3: Создан отчет об ошибке GCC