为什么要将'<'作为'operator<'而不是标记来包围模板参数?

Why take '<' as 'operator<' rather than a mark to enclose the template argument?

本文关键字:lt 包围 参数 作为 operator 为什么      更新时间:2023-10-16

我的C++代码如下:

//test.cpp
#include <iostream>
using namespace std;
template <int SIZE, class T>
struct A
{
    void g(int x, const T& t)
    {
        t.f<SIZE>(x);
    }
};
struct B
{
    template <int SIZE>
    void f(int x) const
    {
        cout << SIZE << ": " << x << endl;
    }
};

int main(void)
{
    A<3, B> a;
    B b;
    a.g(9, b);
    return 0;
}

当我用g++(版本是4.8.2)编译它时,我得到了一个令人惊讶的错误:

test.cpp: In instantiation of ‘void A<SIZE, T>::g(int, const T&) [with int SIZE = 3; T = B]’:
test.cpp:27:13:   required from here
test.cpp:9:12: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
         t.f<SIZE>(x);
            ^

为什么它将<作为operator<,而不是用一个标记来包围模板参数?

因为代码本身就不明确1,所以编译器必须决定哪种方式。C++标准委员会武断地决定,如果有疑问,假设名称是一个变量,而不是类型

如果你希望你的代码被解析为模板,你需要明确地说:

t.template f<SIZE>(x);

1在解析此代码时,t的类型尚不清楚,因为它是一个模板。考虑以下类型:

struct T {
    int f;
};

如果您现在用该类型实例化A,您将得到(由于模板已实例化,因此为伪代码):

void A<3, T>::g(int x, T const& t) {
    ((t.f) < 3) > x;
}

我添加了括号来澄清:编译器就是这样看待代码的,它是完全有效的(尽管毫无意义)。

让我们看看:

t.f < SIZE > (x);

留白并不重要。如果t.f是一个变量,这可以说:做t.f < SIZE,然后做(那个结果)> x

此外,编译器还不知道t.f是一个变量还是一个函数模板。记住,模板可以是专门化的,所以即使现在看起来t.f是一个函数模板;在这篇文章的后面,这个代码可以从B的特殊化中实例化,其中t.f是一个变量。

为了解决这个难题,除非您明确指出它们是其他名称,否则不明确的名称将被视为变量名称。在这种情况下,这是通过编写t.template f来完成的;类似的原理使我们在CCD_ 15是从属名称时编写CCD_。