3

我正在尝试使用 g++ 编译一些 Microsoft Visual C++ 代码。现在我遇到了一个我真的无法理解的编译器错误。(简化的)代码如下所示:

template<int X> struct A {
    template<class Ret> static Ret call() {
        return 0;
    }
};

template<int X> struct B : A<X> {
    int f() {
        return A<X>::call<int>();
    }
};

当我尝试使用 g++(版本 4.4.5)编译它时,我收到以下错误:

main.cpp: In member function int B<X>::f(): 
main.cpp:16: error: expected primary-expression before int 
main.cpp:16: error: expected ; before int
main.cpp:16: error: expected unqualified-id before > token

如果我从方法 A::call 中删除模板类型 (Ret),则代码编译得很好。任何人都可以看到这里有什么问题吗?

谢谢!

4

3 回答 3

5

你需要template关键字:

return A<X>::template call<int>();

call是一个依赖名,意思是它的意义依赖于一个模板参数,这个参数在编译过程中是不知道的f()。您需要通过在其前面加上关键字来表明它call是一个函数模板。template

当您尝试访问嵌套类型时,也会发生同样的事情:您需要添加typename关键字以指示名称表示类型:

template <typename T>
struct A { typedef int type; };

template <typename T>
void f()
{
    typename A<T>::type i = 0; // notice "typename" here
}

有时您甚至需要将两者混合使用:

template <typename T>
struct A
{
    template <typename U>
    struct inner { };
};

template <typename T>
void f()
{
    typename A<T>::template inner<int> var;
}

这两个关键字的使用在这个问题的答案中得到了彻底的解释:我必须将“模板”和“类型名称”关键字放在哪里以及为什么要放置?(感谢@Björn Pollex 找到链接)。

于 2012-01-25T13:58:01.967 回答
5

A是一个模板,在不知道X编译器的情况下无法确定A<X>. 特别是它不知道call最终会成为一个模板。

要告诉编译器,您必须使用template关键字:

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
于 2012-01-25T13:58:46.777 回答
3

您必须指定您正在调用的函数是模板,因为它是模板类的一部分。编译器不知道任何给定A<X>的模板函数名为call,因此您需要帮助它。

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
于 2012-01-25T14:00:01.653 回答