为什么在尝试使用显式类型参数调用模板成员函数时出错?

Cas*_*mor 69 c++ templates metaprogramming

我不明白,在我看来,调用f是完全明确的,但它无法编译expected primary-expression before ‘int’.如果我通过调用注释掉该行f,它编译得很好.

template<typename T>
struct A {
    template<typename S>
    void f() { }
};

template<typename T>
struct B : A<T> {
    void g() {
        this->f<int>();
    }
};
Run Code Online (Sandbox Code Playgroud)

tem*_*def 129

这是由于标准的一个非常模糊的规定,如果你有一个模板试图访问类型取决于模板参数的对象中的模板函数,你必须以template一种奇怪的方式使用该关键字:

this->template f<int>();
Run Code Online (Sandbox Code Playgroud)

typename除了应用于函数之外,这类似于依赖类型的奇怪性.特别是,如果省略template关键字,则解析之间存在歧义

this->f<int>()
Run Code Online (Sandbox Code Playgroud)

(你的意图),和

((this->f) < int) > ()
Run Code Online (Sandbox Code Playgroud)

没有意义(因此你的错误).这里使用关键字template消除歧义并强制编译器识别出它正在查看对模板化成员函数的完全有效调用,而不是大量符号.

希望这可以帮助!

  • 不仅答案是好的,而且还有一个额外的好处,它是由一个名为templatetypedef的用户提供的:-)他肯定知道他在说什么...... (70认同)
  • Visual Studio在某些模板功能上有点松懈.例如,它允许您在技术上需要的几个上下文中省略typename,并自动从不应该的模板库中导入名称.如果这是在C++ 0x而不仅仅是VS中的怪癖,我会感到惊讶. (3认同)
  • @James:你失去了明显错误的早期诊断(缺少`;`,名称拼写错误等等)并且你在重载决策中搞得一团糟(通常,只考虑在模板之前声明的函数,但是这个VC++你可以将之后声明的函数考虑在内,模板的编写者可能没有预料到这一点)...我会说它绝对不会更好.然而,编译器发出这样一个愚蠢的警告是非常愚蠢的(与类型进行比较是没有意义的......),但是gcc从来没有因其用户友好性而被人知道:/ (3认同)
  • 我已经知道模板的一些语法怪异,但我以前从未听过这个. (2认同)
  • @Pedro:它没有,Visual C++是不兼容的,因为它只在实例化时检查模板而不是两阶段查找. (2认同)