如何将父'成员的姓名传递给模板参数?
很难解释,所以我会改为显示短代码。
示例
此代码的A源自Mother。我想将母亲的名字传递给B的模板。
它没有编译。我已经标记了发生错误的行。
class Mother{
public:
int motherField=3;
};
class A: public Mother {
public:
int childField=4;
}; //note: not virtual inherit
template <class T, int T::*a>
class B{ };
int main() {
B<A,&A::motherField> b;
//^ could not convert template argument '&Mother::motherField' to 'int A::*'
}
如果我改变了&#34; motherField&#34; to&#34; childField&#34;,它可以编译。
看起来编译器认为Mother :: motherField与A :: motherField
非常不同我想传递父母的成员,无论如何都要让它编译?
B是一个特殊的hashMap。我们将其命名为AMap。
AMap要求密钥(A)必须为其提供一个字段(可能是int,&#34; motherField&#34; /&#34; childField&#34;在示例中),以缓存一些索引。
AMap<A,&A::dedicatedField1> b1; //I omit the value part for simplicity.
AMap<A,&A::dedicatedField2> b2;
A a1;
b1.cache(a1); //b1 read&write a1.dedicatedField1
b2.cache(a1); //b2 read&write a1.dedicatedField2
这会带来很多性能优势。
b1.get(a1);//b1 just read a1.dedicatedField1, then it know where a1 is stored
为方便起见,我在A之母中提供了一个默认的dedicatedField,所以有时我可以将Mother :: defaultDedicatedField插入AMap(B)。
因此A.h不必包含专用字段,因此代码更清晰。
答案 0 :(得分:1)
指向成员的指针具有他们实际上是其成员的类的类型。因此,即使您编写&A::motherField
,类型也不是int A::*
,而是int Mother::*
。编译错误来自类型不匹配。
您必须将指向成员的指针强制转换为您想要的类型:
B<A, static_cast<int A::*>(&A::motherField)> b;
但这对gcc或clang都不起作用(不明白为什么),所以最好在B
中提供第三个默认类型参数。如果需要,您可以使用最后一种类型来指定派生类 - 例如:
template <class C, int C::*a, class T=C> class B { };
B<Mother, &A::motherField, A> b;