SFINAE применяется, когда подстановка завершается неудачей для параметра шаблона шаблона функции, а не для параметра шаблона шаблона класса, который имеет (не шаблонную) функцию в качестве члена, как в вашем случае.
Послеисправляя это, вы должны по крайней мере изменить decltype(T().apply<0u>(double()))
на decltype(T().template apply<0u>(double()))
, потому что выражение T()
имеет зависимый тип.Причина этого заключается в следующем: когда компилятор впервые видит T().apply<0u>
, он еще ничего не знает о T
, так как он должен анализировать токены apply
и <
после .
?apply
может быть шаблоном члена, а затем <
запустит список аргументов для него.Вместо этого OTOH apply
может быть элементом, не являющимся шаблоном (например, элементом данных), и тогда <
будет проанализирован как оператор «меньше чем».Существует двусмысленность, и пока компилятору еще рано разрешать эту проблему.Существует необходимость в механизме устранения неоднозначности, который программист мог бы использовать, чтобы сообщить компилятору, какой apply
ожидается: шаблоном или нет.И тут на помощь приходит конструкция .template
(или ->template
, или ::template
): если она присутствует, компилятор знает, что это должен быть элемент шаблона, в противном случае, если он отсутствует, то компилятор знает, что член не долженне может быть шаблоном.
Наконец, вот пример, который я создал, который работает правильно и дает желаемые результаты на g ++ 4.5.0 с -std=c++0x
:
#include <iostream>
template < class T >
decltype( T().template apply< 0u >( double() ) ) f( T &t )
{
return t.template apply< 0u >( 5. );
}
const char *f( ... )
{
return "no apply<>";
}
class A {
public:
template < unsigned >
int apply( double d )
{
return d + 10.;
}
};
class B {};
int main()
{
A a;
std::cout << f( a ) << std::endl;
B b;
std::cout << f( b ) << std::endl;
}
Вывод:
15
no apply<>
Теперь, если вы удалите оба .template
из первого определения f()
, то получится:
no apply<>
no apply<>
, который указывает на ошибку замещения для class A
, поскольку он не 'у него есть не шаблонный элемент с именем apply
.СФИНА в действии!