Почему sfinae перегрузка не решена
Эта версия отлично работает:
template<typename T>
struct Foo
{
template<typename U = T>
typename std::enable_if<std::is_same<U,A>::value>::type
bar() { std::cout << "1" << std::endl; }
template<typename U = T>
typename std::enable_if<std::is_same<U,B>::value>::type
bar() { std::cout << "2" << std::endl; }
};
Эта версия не работает:
template<typename T>
struct Foo2
{
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,A>::value>::type >
V bar() { std::cout << "1" << std::endl; }
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,B>::value>::type >
V bar() { std::cout << "2" << std::endl; }
};
с:
ошибка: "шаблон шаблона V Foo2::bar()" не может быть перегружен "шаблоном шаблона V Foo2::bar()"
Разница между обеими версиями заключается в том, что в первой я использую выражение напрямую, во второй я создаю шаблонный параметр по умолчанию и использую его в качестве возвращаемого типа.
В чем причина неудачи во втором примере?
1 ответ
Потому что в случае № 2 два bar
считаются эквивалентными. При рассмотрении вопроса о том, эквивалентны ли два шаблона функции, параметры шаблона по умолчанию игнорируются; они не являются частью сигнатуры шаблона функции. Таким образом, они считаются
template<typename U, typename V>
V bar() { std::cout << "1" << std::endl; }
template<typename U, typename V>
V bar() { std::cout << "2" << std::endl; }
Как видите, они на самом деле эквивалентны.
(акцент мой)
Два функциональных шаблона считаются эквивалентными, если
- они объявлены в одной и той же области
- у них одно и то же имя
- у них одинаковые списки параметров шаблона
- выражения, включающие параметры шаблона в их возвращаемые типы и списки параметров, эквивалентны
Случай № 1 работает, потому что тип возвращаемого значения зависит от параметра шаблона и используется с другим выражением; тогда они считаются не эквивалентными.