让我考虑一个从基本模板类派生的模板类。基类包含一个模板成员。在这种情况下,通常可以使用指针this
从派生类访问基类的成员。但是,当基本成员本身是模板函数时,情况并非如此。
考虑以下代码
#include <iostream>
template <class T>
struct base {
T x;
base() { x = 10; }
template <unsigned int N>
void increment() { x += N; }
};
template <class T>
struct deriv : public base<T> {
using base<T>::base;
void p()
{
using namespace std;
cout << this->x << endl;
base<int>::increment<1>();
// The following statement causes the compile error:
// expected primary-expression before ‘)’ token
// this->increment<1>();
// Also the following statement gives error
// base<T>::increment<1>();
cout << this->x << endl;
}
};
int main()
{
using namespace std;
base<int> A;
cout << A.x << endl;
A.increment<1>();
cout << A.x << endl;
deriv<int> B;
B.p();
return 0;
}
在main
例程中,从类型increment
的变量调用模板成员base
。这没有任何问题。
另一方面,p()
类的成员函数deriv
尝试访问从基继承的模板函数increment
。如上面的注释行中那样使用指针this
this->increment<1>();
给出编译错误
expected primary-expression before ‘)’ token
尝试了一段时间之后,我发现可以像上面的代码一样通过范围运算符访问increment
函数
base<int>::increment<1>();
这将用base
显式实例化T=int
。如果我想从继承的increment
调用base<T>
成员,将通用T
类作为
base<T>::increment<1>();
我收到与上述相同的错误。
我正在使用gcc 8.1.1
问题是:为什么编译器无法使用指针this
来解析继承的成员函数increment
?如何从继承的类increment
实例化继承的模板函数base
?
编辑:我添加了另一种情况,即它无法编译,最好指定问题。
编辑:程序中的小更正,同样的问题。
答案 0 :(得分:2)
除非另行指定,否则编译器会假设您访问的名称不是模板,因此<
和>
都分别标记为小于和大于符号(该行被解析为((this->increment)<1)>()
)。发生这种情况是因为this
和base<T>
都依赖于模板参数T
,并且编译器无法查找increment
来查看它是否是模板。在任何情况下,运算符左侧的名称取决于任何模板参数,而右侧的名称为template-id(带有<>
的名称),则适用。要解决此问题,您需要使用template
关键字
base<T>::template increment<1>();
this->template increment<1>();
为什么base<int>::increment<1>();
会进行编译?由于它不依赖于T
(指的是已知的专业化知识),因此可以查询名称increment
以确定它是否是模板。
但是如果T
不是int
,它将不会编译。 gcc出现以下错误
[x86-64 gcc 8.1 #1] error: type 'base<int>' is not a base type for type 'deriv<long long int>'
如果base<int>::increment
是公共静态的,则代码将始终进行编译(不完全是因为编译器会编译x
不是静态的,而是会进行其他更改)。
答案 1 :(得分:1)
调用this->increment<1>()
是无效的,因为increment
是从属函数模板。因此,您需要使用template
关键字:
this->template increment<1>();
您的using
指令和base<int>::increment<1>()
调用也不正确。如果deriv
的类型不是int
,则两者都不起作用。两者都应使用T
而不是int
。这样做时,由于base<T>::increment<1>()
无效的相同原因,对this->increment<1>()
的调用将变为无效。您还需要在那里的template
关键字:
base<T>::template increment<1>();