Разница в разрешении перегрузки между GCC и clang (SFINAE)

GCC принимает следующий код:

template 
struct meta
{
    typedef typename T::type type;
};

struct S {};

template 
typename meta::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' requested here
typename meta::type foo(T, S);
         ^
test.cpp:10:24: note: while substituting deduced template arguments into function template 'foo' [with T = int]
typename meta::type foo(T, S);
                       ^

Кажется, это предполагает разницу в порядке, в котором GCC и clang выполняют определенные операции при разрешении перегрузки. Похоже, что GCC отбрасывает кандидата в шаблон из-за несоответствия типов во втором параметре (S. противint)перед попыткой создать экземпляр возвращаемого типа кандидата в шаблон, в то время как clang, кажется, делает это наоборот.

Кто прав?

Я считаю, что этот вопрос имеет важное значение для авторов библиотек шаблонов. В частности, если clang прав, автору шаблона fooпридется проделать дополнительную работу, чтобы превратить ошибку в сбой подстановки.

РЕДАКТИРОВАТЬ:Обратите внимание, что следующий немного более простой пример отвергается как GCC, так и clang с аналогичными ошибками:

template 
struct meta
{
    typedef typename T::type type;
};

template 
typename meta::type foo(T);

int foo(int);      

int main()
{
    foo(0);
}

предполагая, что GCC знает, что «только недопустимые типы и выражения в непосредственном контексте типа функции и типов параметров ее шаблона могут привести к сбою вывода».Отличие этого примера от оригинала заключается в наличии в исходном примере второго параметра функции, на основании которого GCC выбрасывает шаблон-кандидата еще до того, как дойдет до попытки выполнить подстановку возвращаемого типа. Я думаю, вопрос в том, правильно ли GCC делать что-то в таком порядке, или он должен пытаться выполнить подстановку возвращаемого типа, прежде чем рассматривать совпадения в типах аргументов.

ОБНОВЛЕНИЕ:Ответ Люка Дантона убедил меня, что clang правильно отклоняет код. Соответственно, я зарегистрировал ошибку GCC .

18
задан Nawaz 15 November 2012 в 18:31
поделиться