模板:模板函数与类的模板成员函数不兼容

Set*_*son 22 c++ templates

这是我实际拥有的一些代码的最小测试用例.它在尝试评估时失败a.getResult<B>():

test.cpp: In function 'void printStuff(const A&)':
test.cpp:6: error: expected primary-expression before '>' token
test.cpp:6: error: expected primary-expression before ')' token
Run Code Online (Sandbox Code Playgroud)

代码是:

#include <iostream>

template< class A, class B>
void printStuff( const A& a)
{
    size_t value = a.getResult<B>();
    std::cout << value << std::endl;
}

struct Firstclass {
    template< class X >
    size_t getResult() const {
        X someInstance;
        return sizeof(someInstance);
    }
};

int main(int, char**) {
    Firstclass foo;

    printStuff<Firstclass, short int>(foo);
    printStuff<Firstclass, double>(foo);

    std::cout << foo.getResult< double >() << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我注释掉printStuff函数及其调用位置,则foo.getResult< double >()调用编译良好并执行预期的操作.

知道发生了什么事吗?我一直在使用广泛模板化的代码,从未遇到过这样的事情.

AnT*_*AnT 40

当您引用属于依赖类型的成员的模板时,必须在其前面加上关键字template.这就是对getResult内部的调用printStuff应该如何看待

size_t value = a.template getResult<B>();
Run Code Online (Sandbox Code Playgroud)

这类似于typename在引用依赖类型中的嵌套类型名时使用关键字.出于某种原因,关于typename嵌套类型的一点是众所周知的,但是对于template嵌套模板的类似要求是相对未知的.

请注意,一般语法结构虽然有点不同.将typename始终放在类型的全名的前面,而template插在中间.

同样,只有在访问依赖类型的模板成员时才需要这样做,在上面的示例中,该模板成员将A在其中printStuff.当你调用foo.getResult<>main的类型foo不依赖,因此没有必要包含template关键字.

  • 哇,就在我以为我知道有关C++的所有知识的时候...... (7认同)
  • 谢谢!这是我在C++中见过的最离奇的语法. (6认同)
  • 不知何故,VC++对此非常宽容(也就是说,没有它你经常会离开),但gcc绝对不是! (3认同)

Kir*_*sky 9

根据C++标准14.2/4,您的代码格式不正确:

当一个构件模板特的名称出现之后.->在一个后缀表达式,或之后嵌套名称说明符在一个合格-ID,和后缀表达或合格-ID明确地依赖于模板参数(14.6.2 ),成员模板名称必须以关键字为前缀template.否则,假定该名称命名非模板.

所以,你应该写 size_t value = a.template getResult<B>();