模板类中结构的 C++ 编译器问题

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

Lou*_*nco 1

在海湾合作委员会,我得到

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 的多次使用都在欺骗它。