Reputation: 432
I would like to write a function that apply a process to member of a class. The following code is working:
class AA
{
public:
AA(){};
~AA(){};
std::string type="AA";
};
class BB
{
public:
BB(){};
~BB(){};
template <typename T, typename TT>
void test(T& a, TT(T::*memberPtr))
{
std::cout<<"test: "<<(a.*memberPtr)<<std::endl;
}
std::string type="BB";
};
int main()
{
AA a;
BB b;
b.test(a, &AA::type);
}
But I know everything at compile-time so I am wondering if it is possible to write something equivalent but only with templates? So I could write something like:
b.test<&AA::type>(a);
that calls inside test(a):
std::cout<<"test: "<< (a.*MEMBER) <<std::endl; // MEMBER is given in template
or something like that.
Upvotes: 6
Views: 4267
Reputation: 304182
You can't do just test<&AA::type>
, since you'd need to also tell the function template what type of pointer-to-member you're expecting. The typical pattern is:
template <class M, M member, class T> // deduced go last
void test(T& a) {
cout << (a.*member);
}
With usage:
test<decltype(&AA::type), &AA::type>
I believe there's currently a proposal to reduce the verbosity there, but until then, it's not the worst thing in the world, and you could always:
#define TYPE_AND_VAL(foo) decltype(foo), foo
test<TYPE_AND_VAL(&AA::type)>
That proposal I mentioned is in C++17, and will allow you to do:
template <auto member, class T>
void test(T& a) {
cout << (a.*member);
}
test<&AA::type>(a);
Upvotes: 11
Reputation: 15334
This is related to SergeyA's answer but a compromise would be to pass your class and a lambda. The compiler is able to inline the lambda so you will probably not pay for it at run-time:
struct BB
{
public:
template <typename T, typename F>
void test(T& a, F f)
{
std::cout<<"test: "<< f(a) <<std::endl;
}
std::string type="BB";
};
int main()
{
AA a;
BB b;
b.test(a, [](AA& a){return a.type;});
}
You may (or may not) find this clearer than using pointer-to-class-member.
Upvotes: 2
Reputation: 62613
Just eliminate this somewhat strongly typed altogether. Instead of requesting user to provide you with a class and the member poiner, just accept templated functor and call it's operator(). This will be most flexible and least verbose.
Upvotes: 0