为何选择'<'作为'运营商<'而不是用于包含模板参数的标记?

时间:2014-09-16 09:20:32

标签: c++ templates

我的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<而不是标记来包含模板参数?

2 个答案:

答案 0 :(得分:7)

因为代码本质上是模糊的 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;
}

我添加了括号以便澄清:这是编译器看到你的代码的方式,它完全有效(虽然没有意义)。

答案 1 :(得分:4)

让我们来看看:

t.f < SIZE > (x);

空白并不重要。如果t.f是变量,则可以说:t.f < SIZE然后执行(结果)> x

此外,编译器还不知道t.f是变量还是函数模板。请记住,模板可以是专用的,因此即使t.f似乎是一个函数模板,也是如此;稍后在这篇文章中,这段代码可以从B的特化中实例化,其中t.f是一个变量。

要解决这个难题,将含糊不清的名称视为变量名,除非您明确指出它们是其他内容。在这种情况下,通过写t.template f来完成;当typename T::iterator是一个从属名称时,类似的原则让我们写T