模板中的模板:为什么“`>>”在嵌套模板参数列表中应该是“> >””

问题描述 投票:0回答:8

我知道当我们在另一个模板中使用模板时,我们应该这样写:

vector<pair<int,int> > s;

如果我们写的时候没有空格:

vector<pair<int,int>> s;

我们会得到一个错误:

`>>' 应该是嵌套模板参数列表中的 `> >'

我觉得这是可以理解的,但我就是忍不住想知道,在什么情况下这会是真的模棱两可?

c++ templates vector lexicographic
8个回答
53
投票

有时您想要它是

>>
。考虑

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

在 C++03 中,这成功解析并创建了一个大小为

256
的数组。


30
投票

永远不会有歧义。事实证明,在 C++0x 中,您不必再在关闭模板

>
之间编写空格。

问题是编译器更愿意尽可能独立于上下文对输入进行标记。由于 C++ 无论如何都不是一种上下文无关的语言,因此仅添加这个特殊情况并不会让事情变得特别困难。


11
投票

在当前标准中,标记化是贪婪的,因此

>>
将被处理为单个标记,就像
a +++ b
将被解析为
a ++ + b
一样。这已经改变并出现了新的标准。虽然它需要编译器实现者做更多的工作,但人们认为总体而言这是值得的(而且一些主要编译器已经将其实现为扩展)。


7
投票

C++ 确实非常难以解析——比大多数其他语言困难得多。 它是一种非常一致的语言,但是在对输入进行标记和理解语法的语法分析之间做了很多工作,以至于对于编译器来说看起来应该很简单的事情通常并非如此。

历史上的“

>>
”运算符是运算符。 当源文件被分解为标记时,它被“识别”。 这些标记随后在语法分析期间在某些上下文中被“理解”(标记化完成后很久)。

如果您在标记化时进行了语法分析,那么您就可以“帮助”来帮助区分“>>”应该被视为模板声明(或定义)的两个闭包。 然而,这并不是历史上 C++ 编译器的工作方式。 (新编译器在语法分析和标记化之间进行更多反馈,包括更多“前瞻”以帮助解决这些歧义。)


是的,新的 C++0x 标准改变了这一点,并迫使编译器供应商重新编写其实现,以消除您的情况下的“

>>

”歧义。 所以,今后的发展,绝不会含糊。 但是,较旧的 C++ 编译器无法处理该问题,因此暂时保持代码与“

>
”字符之间的空格兼容可能被认为是“良好实践”。
    


5
投票
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
进行编译。
    


1
投票


0
投票

产生之前提到的相同错误的行:

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

通过 GCC 交叉编译器并工作的行:

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

对我来说,这只是对该声明的解释上的错误。 


0
投票
流语法

cin >> var;


VS

嵌套模板语法

For<Bar<Barz>>


编译器第一阶段,词法分析器将无法识别。

© www.soinside.com 2019 - 2024. All rights reserved.