18

我收到一个错误 <: cannot begin a template argument list on g++ 编译器。代码

template<typename T> class SomeClass;
class Class;

SomeClass<::Class>* cls;
4

4 回答 4

35

根据Maximal Munch 标记化原则,有效的 C++ 标记必须收集/具有尽可能多的连续字符。

<:是一个有向图(符号 的另一种表示[)。

                           Digraph  Equivalent
                              <:          [
                              :>          ]
                              <%          {
                              %>          }
                              %:          #

所以SomeClass<::Class>* cls;被解释为SomeClass[:Class>* cls;没有任何意义。

<解决方案:在和之间添加一个空格:

  SomeClass< ::Class>* cls;
            ^
            | 
           White Space
于 2010-10-17T09:15:39.280 回答
11

请尝试以下操作:

SomeClass< ::Class>* cls;

您可以在问题中找到有关有向图的更多信息。这个关于三元组的问题也可能会有所帮助。

于 2010-10-17T09:16:23.647 回答
7

使用 C++11,这个问题的答案会有所改变。

预 C++11

在 C++11 之前,最大咀嚼规则用于词法分析以避免歧义,并通过尽可能多的元素来形成有效标记来工作,这导致了这种情况:

<::

生成以下令牌:

<: :

<:是一个有向图,可以转换为[,因此您最终得到:

SomeClass[:Class>* cls;

这不是有效的代码。

2.4 我们可以通过查看 C++ 标准草案的预处理标记部分来确认这种情况,该部分说:

如果输入流已被解析为直到给定字符的预处理标记,则下一个预处理标记是可以构成预处理标记的最长字符序列,即使这会导致进一步的词法分析失败。

并提供了几个例子,包括以下经典的最大咀嚼问题:

[ 示例:程序片段 x+++++y 被解析为 x ++ ++ + y,如果 x 和 y 是内置类型,则违反了对增量运算符的约束,即使解析 x + ++ ++ y 可能会产生正确的表达式。—结束示例]

C++11

在 C++11 中,这一变化为这种情况制定了一条规则,C++11 标准草案添加了以下内容:

否则,如果接下来的三个字符是 <:: 并且后续字符既不是 : 也不是 >,则 < 本身被视为预处理器标记,而不是替代标记 <: 的第一个字符。

到部分2.5 Preprocessing tokens。因此,此代码将不再在 C++11 中产生和错误。

此更改来自缺陷报告:1104

于 2014-07-27T02:19:22.077 回答
2

在 < 字符周围放置空格:

SomeClass < ::Class > * cls;

您实际上只需要分隔 < 和 :,但我喜欢对称。

于 2010-10-17T09:16:46.547 回答