我有一个类模板恰好与某些类的成员函数模板同名。现在,另一个函数模板将使用其中一个具有相关成员函数模板的类进行实例化。要在此函数模板中调用成员函数模板,我需要使用template
关键字,我理解这一点并且没有问题。但是,我需要使用范围解析运算符(我刚发现那就是所谓的)::
来指定我的意思是类的成员函数模板而不是类模板,我不明白为什么。
这是很多模板化的事情,所以让我举个例子:
//class with same name as member function below.
//must be class template or error doesn't show up.
//also no error if this is a function template instead of class
template <class T>
struct f
{
};
struct Base
{
//function with same name as struct above,
//no error if this is not templated
template <int N>
void f(){}
};
//template function that will be instantiated with T=Base.
//no error if this is not templated
template <class T>
void g(T t)
{
//I understand why template keyword is needed here,
//but not why T:: is needed
t.T::template f<0>();
//t.template f<0>(); gives error.
}
有问题的错误是(来自g ++ - 4.7)
error: type/value mismatch at argument 1 in template parameter list for ‘template<class T> struct f’
error: expected a type, got ‘0’
似乎编译器在注释掉的行(没有作用域解析运算符)上解析f<0>()
,试图实例化struct f<0>
类型的对象。我不知道为什么会这样做,我认为它应该能够从t.template
看到我正在尝试访问成员函数模板。
我想了解这里发生了什么,为什么在这种情况下需要T::
,而不是安抚编译器?
似乎在MSVC和Clang下没有问题,所以它似乎是一个特定于g ++的问题。
答案 0 :(得分:1)
我认为这与Two phase lookup有关。特别是Steve Jessops在答案中的注意事项很重要。
答案 1 :(得分:0)
这可能有效
template <class T>
void g(T t)
{
t.T::template f<0>();
}