我在通用上下文中使用指向成员函数的指针,并且可以正常工作。
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);
}
但是,如果我尝试传递静态方法(在Mock
的情况下,它会停止工作,因为静态方法就像普通函数一样。
我需要在user
函数中进行哪些更改,以便它可以编译并正常工作?
我能够使用lambda做到这一点,但这是更多样板代码。
我正在考虑SFINAE或constexpr,但是我不确定如何检测方法是否是静态的。
int main(){
Mock real;
return user(real, &Mock::inc);
}
我正在使用C ++ 17。
具有超载和SFINAE:
template<typename C, typename F>
auto user(C &c, F func) -> decltype((c.*func)(5)) {
return (c.*func)(5);
}
template<typename C, typename F>
auto user(C&, F func) -> decltype(func(5)) {
return func(5);
}
std::is_member_pointer
可用于检测指向成员的指针。然后,您可以执行简单的std::is_member_pointer
来改变它们与应仅接受参数的可调用对象之间的行为。
if constexpr
或者,如果您稍微调整一下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);
}
Mock
然后您可以简单地使用struct Mock{
static int inc(class Real const&, int){
return 0;
}
static int dec(class Real const&, int){
return 0;
}
};
std::invoke