Любой, кто имеет дело с шаблонами, рано или поздно столкнется с чем-то вроде этого
Но подождите, ошибка единственного оператора в 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 г.