Reputation: 6425
How to pass name of parent's member into template argument?
It is hard to explain, so I will show short code instead.
Example
This code has A derived from Mother. I want to pass name of Mother's field into template of B.
It doesn't compile. I have marked the line that error occurs.
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::*'
}
If I change from "motherField" to "childField", it can compile.
It looks like the compiler thinks that Mother::motherField is very different from A::motherField
I want to pass the member of parent, is there anyway to make it compile?
B is a special hashMap. Let's name it AMap.
AMap demand that the keys (A) has to dedicate a field (might be int, "motherField" / "childField" in the example) for it, to cache some index.
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
This creates a lot of performance benefit.
b1.get(a1);//b1 just read a1.dedicatedField1, then it know where a1 is stored
For convenience, I provide a default dedicatedField in Mother of A, so sometimes I can plug Mother::defaultDedicatedField to the AMap (B).
As a result A.h don't have to contain a dedicated field, so code is cleaner.
Upvotes: 2
Views: 129
Reputation: 302862
Pointers to members have the type of the class that they're actually members of. So even though you write &A::motherField
, the type isn't int A::*
but is really int Mother::*
. The compile error comes from the type mismatch.
You'd have to cast the pointer to member to the type you want:
B<A, static_cast<int A::*>(&A::motherField)> b;
But that doesn't work on either gcc or clang (don't understand why yet), so it may be best to provide a 3rd defaulted type parameter in B
instead. You would use that last type to specify a derived class if necessary - like here:
template <class C, int C::*a, class T=C> class B { };
B<Mother, &A::motherField, A> b;
Upvotes: 1