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

时间:2011-07-14 14:54:56

标签: c++ templates compiler-construction vector lexicographic

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

vector<pair<int,int> > s;

如果我们在没有空格的情况下写它:

vector<pair<int,int>> s;

我们会收到错误:

  

`&GT;&GT;”应该是`&gt; &GT;”在嵌套模板参数列表

我觉得这是可以理解的,但我不禁想知道,在哪种情况下,这真的很模糊?

8 个答案:

答案 0 :(得分:48)

有时候你希望它是>>。考虑

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

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

答案 1 :(得分:25)

它永远不会含糊不清。事实证明,在C ++ 0x中,您不必再在关闭模板>之间写入空格。

问题在于编译器更愿意将输入标记为尽可能独立于上下文。由于C ++不是一种与上下文无关的语言,因此只添加这一特殊情况并不会使事情变得特别困难。

答案 2 :(得分:10)

在当前标准中,标记化是贪婪的,因此>>将作为单个标记处理,就像a +++ b将被解析为a ++ + b一样。这已经改变了新标准。虽然它需要编译器实现者的更多工作,但总的来说它是值得的(并且一些主要的编译器已经实现了它作为扩展)。

答案 3 :(得分:6)

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

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

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

是的,新的C ++ 0x标准对此进行了更改,并强制编译器供应商重新编写其实现,以消除您的情况中的“>>”歧义。所以,它永远不会模棱两可。但是,较旧的C ++编译器无法处理,因此将代码与“>”字符之间的空格保持兼容可能被视为“良好做法”。

答案 4 :(得分:1)

这取决于编译器。 Visual Studio没有强制要求它,即两者都有效,而g ++产生错误。我认为这取决于编译器的实现。

答案 5 :(得分:1)

通过设置适当的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 ++方言是带有GNU扩展的C ++ 98。 C ++ 98要求我们编写vector<pair<int, int> >。如果您希望vector<pair<int, int>>使用-std=c++11-std=gnu++11进行更多编译。

答案 6 :(得分:0)

  

流语法

cin >> var;

Vs

  

嵌套模板语法

For<Bar<Barz>>

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

答案 7 :(得分:-1)

我有这个问题用c ++编写一个类,我通过执行以下操作解决了这个问题:

之前产生相同错误的行:

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

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

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

对我而言,对声明的解释只是一个错误。