Подтвердить что ты не робот

Шаблон в шаблоне: почему `` >> должен быть `>> 'в списке вложенных шаблонов шаблонов"

Я знаю, что, когда мы используем шаблон внутри другого шаблона, мы должны написать его следующим образом:

vector<pair<int,int> > s;

и если мы напишем его без пробелов:

vector<pair<int,int>> s;

мы получим сообщение об ошибке:

` → 'должен быть` → ' во вложенном списке аргументов шаблона

Я понимаю, что это понятно, но я просто не могу не задаться вопросом, в каких случаях это будет действительно двусмысленно?

4b9b3361

Ответ 1

Иногда вы хотите, чтобы он был >>. Рассмотрим

boost::array<int, 1024>>2> x;

В С++ 03 это успешно анализирует и создает массив размером 256.

Ответ 2

Это никогда не будет двусмысленным. Это подтверждается тем фактом, что в С++ 0x вам больше не нужно писать пробел между закрывающим шаблоном >.

Дело в том, что компиляторы предпочли бы токенизировать ввод как можно более контекстно-зависимым. Поскольку С++ не является контекстно-зависимым языком, добавление только этого особого случая не будет делать вещи особенно сложными.

Ответ 3

В текущем стандарте токенизация является жадной, поэтому >> будет обрабатываться как один токен, так же, как a +++ b будет анализироваться как a ++ + b. Это изменило и новый стандарт. Хотя это требует больше работы от разработчиков компиляторов, было сочтено, что в целом оно того стоит (и некоторые крупные компиляторы уже реализуют это как расширение в любом случае).

Ответ 4

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

Исторический оператор ">>" является оператором. Он "идентифицируется", поскольку исходный файл разбивается на токены. Затем эти жетоны затем "понимаются" в некотором контексте во время грамматического анализа (долго после того, как токенизация завершена).

Если вы выполняли грамматический анализ, пока вы токенизировали, то вы "помогаете" помогать в различии, которое ">>" следует рассматривать как два замыкания на объявление шаблона (или определение). Тем не менее, это исторически не то, как работают исторические компиляторы С++. (Новые компиляторы делают больше обратной связи между грамматическим анализом и токенизацией, в том числе более "надежными", чтобы помочь решить эти двусмысленности.)

Да, новый стандарт С++ 0x меняет это и заставляет компиляторы переписывать свои реализации, чтобы устранить ">>" в вашем случае. Таким образом, он никогда не будет двусмысленным в будущем. Однако старые компиляторы С++ не могут справиться с этим, поэтому можно считать "хорошей практикой" поддерживать совместимость вашего кода с пробелом между символами ">".

Ответ 5

Это зависит от компилятора. Visual Studio не требует этого, то есть оба работают, а g++ создает ошибку. Я думаю, что это зависит от реализации компилятора.

Ответ 6

Избегайте этой ошибки, установив соответствующий диалект С++. Например, с gcc 4.9 следующий файл не скомпилируется с g++:

#include <vector>
#include <utility>

int main()
{
    using namespace std;
    vector<pair<int, int>> v; // compile error!
    return 0;
}

Позвольте понять суть вещей:

#include <iostream>

int main()
{
    std::cout << __cplusplus << std::endl;
    return 0;
}

Скомпилированный с помощью всего лишь g++ test.cpp этот код печатает 199711. Хотя gcc 4.9 был выпущен в 2014 году, диалект С++ по умолчанию - это С++ 98 с расширениями GNU. Для С++ 98 требуется написать vector<pair<int, int> >. Если вам нравится vector<pair<int, int>> скомпилировать с -std=c++11 или -std=gnu++11.

Ответ 7

Синтаксис потока

cin >> var;

Vs

Синтаксис вложенных шаблонов

For<Bar<Barz>>

Первая фаза компилятора, лексический анализатор не сможет распознать.

Ответ 8

У меня была проблема с программированием класса в С++, и я решил это, выполнив следующие действия:

Линия, которая произвела ту же ошибку, о которой упоминалось выше:

findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector<std::vector<cv::Point»&);

Линия, которая прошла через GCC Cross Compiler и Worked:

findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector< std::vector<cv::Point> >&);

Для меня это была просто ошибка в интерпретации заявления.