I have this template method:
template <class SomeLhs, class SomeRhs,
ResultType (SomeLhs::*callback)(SomeRhs&)>
void Add() {
struct Local {
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) {
return (static_cast<SomeLhs&>(lhs).*callback)(static_cast<SomeRhs&>(rhs));
}
};
_back_end.template Add<SomeLhs,SomeRhs>(&Local::Trampoline);
}
Currently I'm calling it like this:
tracker.Add<Quad, Multi, &Quad::track>();
tracker.Add<Quad, Singl, &Quad::track>();
tracker.Add<Sext, Multi, &Sext::track>();
...
It is working fine, but I don't like to have to repeat two times the name of class SomeLhs
. Is there a way to avoid that?
For people who may have recognized it: yes, this is related to the BasicFastDispatcher of Alexandrescu, in particular I'm writing a front end to operate with member functions.
I don't think it can't be improved particularly, which is unfortunate as I'd love to find a way to do this.
Template type deduction is only possible for function template arguments and you need to pass in the non-type member function pointer at compile time in order for it to be treated as a name rather than a varying quantity. Which means having to specify all the args.
i.e. you can do this:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (SomeLhs::*callback)(SomeRhs&)) {
...
}
// nice syntax:
tracker.Add(&Sext::track);
// But ugly for overloaded functions, a cast is needed.
// p.s. not sure this is exactly the right syntax without compiling it.
tracker.Add((ResultType (Quad::*)(Multi&) &Quad::track);
But then you have an actual pointer that cannot subsequently be used as a template parameter.
The only thing I think you could do is to use a macro, though it is arguable if it really improves syntax here. I'd say it probably adds an unnecessary level of obfuscation.
e.g.
#define TMFN_ARGS(C, M, P1) C, P1, &C::M
tracker.Add<TMFN_ARGS(Quad, track, Multi)>();
EDIT:
However, if the name of the function is Always 'track', you could do something along the following lines:
template <typename C, typename P1>
void AddTrack() {
Add<C, P1, &C::track>();
}
tracker.AddTrack<Quad, Multi>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With