我收到一个错误 <: cannot begin a template argument list on g++ 编译器。代码
template<typename T> class SomeClass;
class Class;
SomeClass<::Class>* cls;
我收到一个错误 <: cannot begin a template argument list on g++ 编译器。代码
template<typename T> class SomeClass;
class Class;
SomeClass<::Class>* cls;
根据Maximal Munch 标记化原则,有效的 C++ 标记必须收集/具有尽可能多的连续字符。
<:
是一个有向图(符号 的另一种表示[
)。
Digraph Equivalent
<: [
:> ]
<% {
%> }
%: #
所以SomeClass<::Class>* cls;
被解释为SomeClass[:Class>* cls;
没有任何意义。
<
解决方案:在和之间添加一个空格:
SomeClass< ::Class>* cls;
^
|
White Space
使用 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
在 < 字符周围放置空格:
SomeClass < ::Class > * cls;
您实际上只需要分隔 < 和 :,但我喜欢对称。