我知道当我们在另一个模板中使用模板时,我们应该这样写:
vector<pair<int,int> > s;
如果我们写的时候没有空格:
vector<pair<int,int>> s;
我们会得到一个错误:
`>>' 应该是嵌套模板参数列表中的 `> >'
我觉得这是可以理解的,但我就是忍不住想知道,在什么情况下这会是真的模棱两可?
有时您想要它是
>>
。考虑
boost::array<int, 1024>>2> x;
在 C++03 中,这成功解析并创建了一个大小为
256
的数组。
永远不会有歧义。事实证明,在 C++0x 中,您不必再在关闭模板
>
之间编写空格。
问题是编译器更愿意尽可能独立于上下文对输入进行标记。由于 C++ 无论如何都不是一种上下文无关的语言,因此仅添加这个特殊情况并不会让事情变得特别困难。
在当前标准中,标记化是贪婪的,因此
>>
将被处理为单个标记,就像a +++ b
将被解析为a ++ + b
一样。这已经改变并出现了新的标准。虽然它需要编译器实现者做更多的工作,但人们认为总体而言这是值得的(而且一些主要编译器已经将其实现为扩展)。
C++ 确实非常难以解析——比大多数其他语言困难得多。 它是一种非常一致的语言,但是在对输入进行标记和理解语法的语法分析之间做了很多工作,以至于对于编译器来说看起来应该很简单的事情通常并非如此。
历史上的“
>>
”运算符是运算符。 当源文件被分解为标记时,它被“识别”。 这些标记随后在语法分析期间在某些上下文中被“理解”(标记化完成后很久)。
如果您在标记化时进行了语法分析,那么您就可以“帮助”来帮助区分“>>
”应该被视为模板声明(或定义)的两个闭包。 然而,这并不是历史上 C++ 编译器的工作方式。 (新编译器在语法分析和标记化之间进行更多反馈,包括更多“前瞻”以帮助解决这些歧义。)
是的,新的 C++0x 标准改变了这一点,并迫使编译器供应商重新编写其实现,以消除您的情况下的“
>>
”歧义。 所以,今后的发展,绝不会含糊。 但是,较旧的 C++ 编译器无法处理该问题,因此暂时保持代码与“
>
”字符之间的空格兼容可能被认为是“良好实践”。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++ 方言是具有 GNU 扩展的 C++98。 C++98要求我们写
vector<pair<int, int> >
。如果您更喜欢vector<pair<int, int>>
,请使用-std=c++11
或-std=gnu++11
进行编译。
产生之前提到的相同错误的行:
findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector<std::vector<cv::Point»&);
通过 GCC 交叉编译器并工作的行:
findAndDrawContoursFrame(cv::Mat&,cv::Mat&,std::vector< std::vector<cv::Point> >&);
对我来说,这只是对该声明的解释上的错误。
cin >> var;
VS
嵌套模板语法
For<Bar<Barz>>
编译器第一阶段,词法分析器将无法识别。