Ответ 1
Иногда вы хотите, чтобы он был >>
. Рассмотрим
boost::array<int, 1024>>2> x;
В С++ 03 это успешно анализирует и создает массив размером 256
.
Я знаю, что, когда мы используем шаблон внутри другого шаблона, мы должны написать его следующим образом:
vector<pair<int,int> > s;
и если мы напишем его без пробелов:
vector<pair<int,int>> s;
мы получим сообщение об ошибке:
` → 'должен быть` → ' во вложенном списке аргументов шаблона
Я понимаю, что это понятно, но я просто не могу не задаться вопросом, в каких случаях это будет действительно двусмысленно?
Иногда вы хотите, чтобы он был >>
. Рассмотрим
boost::array<int, 1024>>2> x;
В С++ 03 это успешно анализирует и создает массив размером 256
.
Это никогда не будет двусмысленным. Это подтверждается тем фактом, что в С++ 0x вам больше не нужно писать пробел между закрывающим шаблоном >
.
Дело в том, что компиляторы предпочли бы токенизировать ввод как можно более контекстно-зависимым. Поскольку С++ не является контекстно-зависимым языком, добавление только этого особого случая не будет делать вещи особенно сложными.
В текущем стандарте токенизация является жадной, поэтому >>
будет обрабатываться как один токен, так же, как a +++ b
будет анализироваться как a ++ + b
. Это изменило и новый стандарт. Хотя это требует больше работы от разработчиков компиляторов, было сочтено, что в целом оно того стоит (и некоторые крупные компиляторы уже реализуют это как расширение в любом случае).
С++ действительно невероятно сложно разобрать - гораздо сложнее, чем большинство других языков. Это очень согласованный язык, но так много работы делается между токенизацией ввода и пониманием грамматического анализа синтаксиса, что вещи, которые кажутся им, должны быть простыми для компилятора, часто НЕ.
Исторический оператор ">>
" является оператором. Он "идентифицируется", поскольку исходный файл разбивается на токены. Затем эти жетоны затем "понимаются" в некотором контексте во время грамматического анализа (долго после того, как токенизация завершена).
Если вы выполняли грамматический анализ, пока вы токенизировали, то вы "помогаете" помогать в различии, которое ">>
" следует рассматривать как два замыкания на объявление шаблона (или определение). Тем не менее, это исторически не то, как работают исторические компиляторы С++. (Новые компиляторы делают больше обратной связи между грамматическим анализом и токенизацией, в том числе более "надежными", чтобы помочь решить эти двусмысленности.)
Да, новый стандарт С++ 0x меняет это и заставляет компиляторы переписывать свои реализации, чтобы устранить ">>
" в вашем случае. Таким образом, он никогда не будет двусмысленным в будущем. Однако старые компиляторы С++ не могут справиться с этим, поэтому можно считать "хорошей практикой" поддерживать совместимость вашего кода с пробелом между символами ">
".
Это зависит от компилятора. Visual Studio не требует этого, то есть оба работают, а g++ создает ошибку. Я думаю, что это зависит от реализации компилятора.
Избегайте этой ошибки, установив соответствующий диалект С++. Например, с 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
.
Синтаксис потока
cin >> var;
Vs
Синтаксис вложенных шаблонов
For<Bar<Barz>>
Первая фаза компилятора, лексический анализатор не сможет распознать.
У меня была проблема с программированием класса в С++, и я решил это, выполнив следующие действия:
Линия, которая произвела ту же ошибку, о которой упоминалось выше:
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> >&);
Для меня это была просто ошибка в интерпретации заявления.