I am using pointer to member function in generic context and It works OK.
struct Mock{
static int inc(int){
return 0;
}
static int dec(int){
return 0;
}
};
struct Real{
Real(int v) : v(v){}
int inc(int a) const{
return a + v;
}
int dec(int a) const{
return a - v;
}
private:
int v;
};
template<typename C, typename F>
auto user(C &c, F func){
return (c.*func)(5);
}
int main(){
Real real(5);
return user(real, &Real::inc);
}
However if I try to pass static method (in case of Mock
), it stops working, because static method is like normal function.
What I need to change in user
function, so this compiles and work properly?
I was able to do it with lambda, but it was way more boilerplate code.
I am thinking of SFINAE or constexpr if, but I am not sure how to detect if method is static.
int main(){
Mock real;
return user(real, &Mock::inc);
}
I am using C++17.
std::is_member_pointer
can be used to detect pointers to members. You can then do a simple if constexpr
to vary the behavior between those and a callable that should accept just the argument.
template<typename C, typename F>
auto user(C &c, F func){
if constexpr (std::is_member_pointer_v<F>)
return (c.*func)(5);
else
return func(5);
}
Alternatively, if you restructure your Mock
a bit
struct Mock{
static int inc(Mock const&, int){
return 0;
}
static int dec(Mock const&, int){
return 0;
}
};
Then you can simply use std::invoke
template<typename C, typename F>
auto user(C &c, F func){
return std::invoke(func, c, 5);
}