【问题标题】:Templates: template function not playing well with class's template member function [duplicate]模板:模板函数不能很好地与类模板成员函数配合使用
【发布时间】:2010-12-13 13:28:32
【问题描述】:

这是我实际拥有的一些代码的最小测试用例。它在尝试评估 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

代码是:

#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;
}

如果我注释掉 printStuff 函数及其调用位置,则 foo.getResult&lt; double &gt;() 调用可以正常编译并执行预期操作。

知道发生了什么吗?我一直在使用大量模板代码,但从未遇到过这样的事情。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    当你引用一个属于依赖类型成员的模板时,你必须在它前面加上关键字template。这就是在printStuff 中调用getResult 的样子

    size_t value = a.template getResult<B>();
    

    这类似于在引用依赖类型中的嵌套类型名时使用关键字typename。出于某种原因,关于嵌套类型的typename 的知识相当广为人知,但对于嵌套模板的template 的类似要求却相对不为人知。

    请注意,一般语法结构有点不同。 typename 总是放在类型全名的前面,而template 放在中间。

    同样,这仅在您访问 依赖类型 的模板成员时是必需的,在上面的示例中为 AprintStuff。当您在main 中调用foo.getResult&lt;&gt; 时,foo 的类型不依赖,因此无需包含template 关键字。

    【讨论】:

    • 谢谢!这是我在 C++ 中见过的最奇怪的语法。
    • 不知何故 VC++ 对它很宽容(也就是说,没有它你经常可以逃脱),但 gcc 绝对不是!
    • 在所有三点上都完全同意你们的观点,除了我发现 gcc 在使用 CodeSourcery 交叉编译 ARM 之前也很宽容。
    • 哇,我以为我对 C++ 语法也了如指掌;我共同编写了一个 C++ 前端,但我不知道这个
    【解决方案2】:

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

    当成员模板特化的名称出现在 postfix-expression 中的 .-&gt; 之后,或 nested-name-specifier 之后em>qualified-id,并且后缀表达式或qualified-id显式依赖于模板参数(14.6.2),成员模板名称必须以关键字template为前缀。否则,该名称被假定为命名一个非模板。

    所以,你应该写size_t value = a.template getResult&lt;B&gt;();

    【讨论】:

      猜你喜欢
      • 2021-09-11
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2011-05-28
      • 2013-07-02
      相关资源
      最近更新 更多