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


13

以下代码无法使用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;
};

错误消息是

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);

该错误是由模板类foo引起的。当写<=而不是<1时,它也会编译。

任何提示表示赞赏吗?

CompilerExplorer链接https://godbolt.org/z/v6Tygo


7
我会说编译器错误,但msvc是唯一接受它的:-/ Demo。可能的解决方法b.bar::foo括号((this->b.foo) < 1
Jarod42

Answers:


1

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

so.cpp:8:27: error: expected '>'
    if(this->b.foo < 1) 
                      ^

因此,编译器认为该foo行上的代码引用了foo上面的类,并且期望使用模板参数。这类似于您所看到的。

当您将其更改<=为时,词法分析器会将其标记为单个标记。下一阶段甚至都看不到<,因此它不会引起混淆。

如果将类更改为与long中的名称不同bar,则不会出现此问题。此外,@ Jarod42在他对您的问题的评论中有建议(更多限定条件或原谅)。

编译器是分阶段编写的,其中每个阶段将代码转换为下一个更好的表示形式,并且每个阶段可以使用该表示形式执行越来越复杂的事情。

首先,编译器将代码“词法化”,从而将文件中的各个字符转换为令牌流-它将看到此行类似于

// if(this->b.foo < 1) 
- keyword(if)
- left-paren
- keyword(this)
- operator(->)
- name(b)
- operator(.)

然后到达foo。它可能应该做

- name(foo)
- operator(<)
- number(1)
- right-paren

但是,在我看来foo,它看起来就像是,它向前看,看到存在<的事实,foo<class T>并且它试图从中制造出单个令牌,foo< ...但是却找不到>要完成的令牌。

这只是猜测-可能是词法分析器经过的一个阶段,该过程试图查找名称并可以组合标记。无论如何,foo的多种用途正在欺骗它。


我理解您的解释,但是不确定这是否意味着编译器应该采取这种方式。也许应该将其作为不同编译器的bug。有时,您可能不清楚链接库头中包含哪些模板类(通用名称,如cnt,count,counter ...)
eactor

我认为这是一个错误,但我不知道该规范怎么说。在C ++中,常见的问题是来自第三方标头的名称引起的问题-通常可以通过限定条件解决。
Lou Franco
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.