Любой, кто имеет дело с шаблонами, рано или поздно столкнется с чем-то вроде этого

Но подождите, ошибка единственного оператора в f()

В данном случае ошибка gcc очень хороша, поскольку нам нужно добавить ведущее имя типа, чтобы это получилось:

typename Obj<T>::type var;

Ведущее имя сообщает компилятору, что Obj<T>::type является типом. Но зачем нам это нужно? Мы знаем, что Obj<T> является зависимым типом, потому что он зависит от T.

Во-первых, вы должны понимать, что без ведущего имени типа компилятор предполагает (в случае зависимого типа), что это статическая переменная-член, что означает, что следующая информация анализируется правильно

И что? Почему компилятор не может просто заглянуть внутрь Obj и увидеть, что у него есть член type. Что ж, в случае со специализацией по шаблонам это невозможно. Учти это:

Внутри f() мы не знаем, с какой из них имеем дело. f() обычно означает, что используется общий шаблон, но f<int>() использует специализацию. Программист должен уточнить, что они ожидают типа.

Вы можете подумать: «Верно, но в данном случае ясно, что тело f() объявляет переменную». Вы правы, но не всегда так однозначно. Что, если бы вместо этого у нас было

Теперь у нас есть две возможные версии этого

Обе эти строки имеют смысл, но означают очень разные вещи. Не всегда ясно, каким образом его следует анализировать.

«Точечный шаблон»

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

Теперь давайте создадим переменную с зависимым типом Obj<T> и вызовем m()

Но подождите, у нас есть ошибки! на этот раз лязг быть более полезным

Хм? ключевое слово шаблона? Что происходит, так это то, что компилятор не знает, что m является шаблонной функцией-членом, нам нужно сообщить ей

Хорошо, а какая альтернатива? Что ж, это довольно хорошо известная проблема грамматики C ++, заключающаяся в том, что без контекста вы не знаете, что означают определенные строки. Заимствуя из документов D, рассмотрите строку:

A<B,C>D;

Это может означать две вещи: (1) A - шаблонный класс, B и C - аргументы шаблона, а D - переменная, объявленная с этим типом. Например:

Или (2), A, B, C и D - все переменные, и это два сравнения, разделенные запятой.

Итак, по умолчанию компилятор предполагает, что m не шаблон, что означает, что он предполагает, что угловые скобки меньше и больше операторов, поэтому он анализируется как

Это могло иметь смысл в другом контексте

Таким образом, «точечный шаблон» необходим, чтобы сказать, что то, что следует ниже, является шаблоном. Как я уже сказал, это встречается гораздо реже, а синтаксис настолько неудобен, что может влиять на дизайнерские решения. Если вы когда-нибудь задумывались, почему std::get является бесплатной функцией, то важно то, что std::tuple часто используется как зависимый тип.

Первоначально опубликовано на makecleanandmake.com 20 июля 2015 г.