Разница в разрешающей способности при перегрузке между GCC и clang (SFINAE)
GCC принимает следующий код:
template <typename T>
struct meta
{
typedef typename T::type type;
};
struct S {};
template <typename T>
typename meta<T>::type foo(T, S);
int foo(int, int);
int main()
{
foo(0, 0);
}
Но Clang отклоняет это со следующей ошибкой:
test.cpp:4:22: error: type 'int' cannot be used prior to '::' because it has no members
typedef typename T::type type;
^
test.cpp:10:10: note: in instantiation of template class 'meta<int>' requested here
typename meta<T>::type foo(T, S);
^
test.cpp:10:24: note: while substituting deduced template arguments into function template 'foo' [with T = int]
typename meta<T>::type foo(T, S);
^
Кажется, это указывает на разницу в порядке, в котором GCC и clang выполняют определенные операции во время разрешения перегрузки. GCC, кажется, выбрасывает кандидата шаблона из-за несоответствия типов во втором параметре (S
противint
) before попытка создания экземпляра возвращаемого типа шаблона-кандидата, в то время как clang, кажется, делает это наоборот.
Кто прав?
Я считаю, что этот вопрос имеет важные последствия для авторов библиотек шаблонов. В частности, если clang прав, автор шаблонаfoo
пришлось бы сделать дополнительную работу, чтобы превратить ошибку в ошибку замены.
EDITОбратите внимание, что следующий чуть более простой пример отклонен как GCC, так и clang с похожими ошибками:
template <typename T>
struct meta
{
typedef typename T::type type;
};
template <typename T>
typename meta<T>::type foo(T);
int foo(int);
int main()
{
foo(0);
}
предполагая, что GCC знает, что «только недопустимые типы и выражения в непосредственном контексте типа функции и ее типов параметров шаблона могут привести к ошибке вывода». Разница между этим примером и оригиналом заключается в наличии второго параметра функции в исходном примере, на основе которого GCC выбрасывает кандидата-шаблона, прежде чем он даже попытается выполнить замену возвращаемого типа. Я думаю, что вопрос заключается в том, является ли GCC правильным, чтобы делать вещи в таком порядке, или он должен пытаться выполнить подстановку возвращаемого типа перед рассмотрением совпадений в типах аргументов.
UPDATEОтвет Люка Дантона убедил меня в том, что clang правильно отклоняет код. У меня соответственноподал ошибку GCC.