Почему 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 работает, потому что тип возвращаемого значения зависит от параметра шаблона и используется с другим выражением; тогда они считаются не эквивалентными.

Другие вопросы по тегам