Как псевдонимы шаблона влияют на вывод параметров шаблона? - PullRequest
12 голосов
/ 08 января 2012

В 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 ]

9 голосов
/ 08 января 2012

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

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

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 не может быть выведен.

1 голос
/ 08 января 2012

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

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

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

1 голос
/ 08 января 2012

Представьте себе это:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...