Как псевдонимы шаблона влияют на вывод параметров шаблона?
В 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:
Когда идентификатор шаблона ссылается на специализацию шаблона псевдонима, он эквивалентен связанному типу, полученному путем подстановки его аргументов шаблона для параметров шаблона в идентификаторе типа шаблона псевдонима. [Примечание: имя шаблона псевдонима никогда не выводится. - конец примечания]
За цитатой следует пример, в котором говорится, что бессмысленно использовать шаблон псевдонима в шаблоне функции и надеяться получить аргумент шаблона. Это, очевидно, применимо даже к ситуации, в которой нет вложенных типов.