指向模板上下文中的成员函数或静态函数的指针

问题描述 投票:0回答:1

我在通用上下文中使用指向成员函数的指针,并且可以正常工作。

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。

c++ templates c++17 function-pointers
1个回答
0
投票

具有超载和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);
}

0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.