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

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

vector<pair<int,int> > s;

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

vector<pair<int,int>> s;

мы получим ошибку:

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

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

7 ответов

Решение

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

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

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

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

Дело в том, что компиляторы предпочли бы маркировать ввод как можно более независимым от контекста. Так как C++ в любом случае не является независимым от контекста языком, добавление только этого особого случая не усложнит ситуацию.

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

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

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

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

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

Избегайте этой ошибки, устанавливая соответствующий диалект C++. Например, с 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 году, по умолчанию диалект C++ - это C++98 с расширениями GNU. C++98 требует от нас написать vector<pair<int, int> >, Если хочешь vector<pair<int, int>> больше компилировать с -std=c++11 или же -std=gnu++11,

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

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

cin >> var;

Против

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

For<Bar<Barz>>

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

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

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

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

Строка, прошедшая через GCC Cross Compiler и работающая:

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

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

Другие вопросы по тегам