123*_*3tv 13 c++ templates compiler-errors compiler-bug
以下代码不能用 gcc 或 clang 编译。
template<class T>
class foo{};
template<class T>
class template_class_with_struct
{
void my_method() {
if(this->b.foo < 1);
};
struct bar
{
long foo;
} b;
};
Run Code Online (Sandbox Code Playgroud)
错误信息是
error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'
8 | if(this->b.foo < 1);
Run Code Online (Sandbox Code Playgroud)
该错误是由模板类 foo 引起的。当编写 <= 而不是 < 1 时,它也会编译。
任何提示赞赏?
CompilerExplorer 链接https://godbolt.org/z/v6Tygo
在海湾合作委员会,我得到
so.cpp:8:27: error: expected '>'
if(this->b.foo < 1)
^
Run Code Online (Sandbox Code Playgroud)
因此,编译器认为foo该行上的 引用上面的类foo并且需要模板参数。这与您所看到的类似。
当您将其更改为 时<=,词法分析器会将其标记为单个标记。下一阶段甚至看不到 a <,因此不会被它迷惑。
如果您将类更改为与 long in 不具有相同的名称bar,则它不会出现此问题。另外,@Jarod42 在对您的问题的评论中提出了建议(更多限定条件或括号)。
编译器是分阶段编写的,每个阶段都会将代码转换为下一个阶段的更好的表示,并且每个阶段都可以使用该表示来做越来越复杂的事情。
一开始,编译器“词法分析”代码,将文件中的各个字符转换为标记流 - 它将将此行视为类似
// if(this->b.foo < 1)
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)
Run Code Online (Sandbox Code Playgroud)
然后它到达foo. 它可能应该做
- name(foo)
- operator(<)
- number(1)
- right-paren
Run Code Online (Sandbox Code Playgroud)
但是,在我看来,当它看到 时foo,它会向前看,看到存在的<事实foo<class T>,并尝试从中创建一个令牌foo< ...,但随后找不到来>完成它。
这只是一个猜测——它可能是经过词法分析器尝试查找名称并可以组合标记的阶段。无论如何, foo 的多次使用都在欺骗它。