Как псевдонимы шаблона влияют на вывод параметров шаблона?

В C++03 вывод параметров шаблона не происходит в некоторых контекстах. Например:

template <typename T> struct B {};

template <typename T>
struct A
{
    typedef B<T> type;
};

template <typename T>
void f(typename A<T>::type);

int main()
{
    B<int> b;
    f(b);  // ERROR: no match
}

Вот, int не выводится для T потому что вложенный тип, такой как A<T>::type является не выводимым контекстом

Если бы я написал функцию следующим образом:

template <typename T> struct B {};

template <typename T>
void f(B<T>);

int main()
{
    B<int> b;
    f(b);
}

все хорошо, потому что B<T> это выводимый контекст.

Однако в C++11 псевдонимы шаблонов могут использоваться для маскировки вложенного типа в синтаксисе, аналогичном второму примеру. Например:

template <typename T> struct B {};

template <typename T>
struct A
{
    typedef B<T> type;
};

template <typename T>
using C = typename A<T>::type;

template <typename T>
void f(C<T>);

int main()
{
    B<int> b;
    f(b);
}

Будет ли в этом случае работать вычет аргументов шаблона? Другими словами, являются ли псевдонимы шаблонов выводимым контекстом или не выводимым контекстом? Или они наследуют выведенный / не выведенный статус любого псевдонима?

3 ответа

Решение

Другими словами, являются ли псевдонимы шаблонов выводимым контекстом или не выводимым контекстом?

Они выводятся так же, как и эквивалентный код, без использования псевдонимов шаблона. Например

template<typename T>
using ref = T&;

template<typename T>
void f(ref<T> r);

Теперь вы можете позвонить f(x) а также T будет выведен на отлично Во время определения f уже, ref<T> заменяется типом T&, А также T& это выводимый контекст.

В твоем случае C<T> заменяется typename A<T>::typeи это не выводимый контекст для T, так T не может быть выведено.

Вообразите это:

template <typename T> struct Foo { typedef   T type; }
template <> struct Foo<char>     { typedef int type; }

template <typename T> using mytype = typename Foo<T>::type;

template <typename T> void f(mytype<T>);

Теперь, если я хочу int n; f(n);как я могу решить, хочу ли я T = int или же T = char? Вся проблема, на которую не влияют псевдонимы шаблонов, состоит в том, что вы не можете сделать вывод назад ко всем вещам, которые могли бы что-то определить.

Я думаю, что соответствующая цитата в стандарте C++ - 14.5.7 [temp.alias] параграф 2:

Когда идентификатор шаблона ссылается на специализацию шаблона псевдонима, он эквивалентен связанному типу, полученному путем подстановки его аргументов шаблона для параметров шаблона в идентификаторе типа шаблона псевдонима. [Примечание: имя шаблона псевдонима никогда не выводится. - конец примечания]

За цитатой следует пример, в котором говорится, что бессмысленно использовать шаблон псевдонима в шаблоне функции и надеяться получить аргумент шаблона. Это, очевидно, применимо даже к ситуации, в которой нет вложенных типов.

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