C++ 将重载成员函数传递给函数模板

C++ 将重载成员函数传递给函数模板,c++,c++14,c++17,template-meta-programming,C++,C++14,C++17,Template Meta Programming,我想要一个函数,它调用一个给定的成员函数,并提供可变输入参数。我写了这样的东西: #include <type_traits> #include <utility> struct A { constexpr int show(int a, int b) const noexcept {return a + b;} }; template <typename T, typename MemFn, typename ... Args> int

我想要一个函数,它调用一个给定的成员函数,并提供可变输入参数。我写了这样的东西:

#include <type_traits>
#include <utility>    

struct A {
    constexpr int show(int a, int b) const noexcept {return a + b;}
};

template <typename T, typename MemFn, typename ... Args>
int show(T && obj, MemFn Fn, Args&&... args)
{
    return (obj.*Fn)(std::forward<Args>(args)...);
}

int main()
{
    constexpr A a;
    return show(a, &A::show, 1, 2);
}
编译器无法推断成员函数的类型,这真的很有意义,但我想知道是否有解决这个问题的方法,比如在成员函数模板中嵌入输入参数类型之类的

可以找到示例代码

我想知道是否有解决这个问题的方法,比如在成员函数模板中嵌入输入参数类型或其他什么

使用lambdas而不是对象和成员函数指针。例如:

struct A {
    constexpr int show(int a, int b) const noexcept {return a + b;}
    constexpr int show(int a) const noexcept {return a * 3;}
};

template <typename F, typename ... Args>
int show(F&& f, Args&&... args) {
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

int main() {
    constexpr A a;
    auto f = [&a](auto... args) { return a.show(std::forward<decltype(args)>(args)...); };
    show(f, 1);
    show(f, 1, 2);
}
结构A{ constexpr int show(int a,int b)const noexcept{返回a+b;} constexpr int show(int a)const noexcept{返回a*3;} }; 模板 整型显示(F&&F,参数&&…参数){ 返回std::forward(f)(std::forward(args)…); } int main(){ constexpr A; auto f=[&a](auto…args){返回a.show(std::forward(args)…;}; 显示(f,1); 显示(f,1,2); }
您可以为成员函数使用更具体的类型来约束函数:

template <typename T, typename... Args>
int show(T && obj, int(std::remove_reference_t<T>::*Fn)(int, int) const, Args&&... args)
{
    return (obj.*Fn)(std::forward<Args>(args)...);
}
模板
int show(T&&obj,int(std::remove_reference_T::*Fn)(int,int)常量、参数和参数)
{
返回(obj.*Fn)(标准:转发(args)…);
}

然而,根据您的用例,此定义可能过于受限,因为现在
Fn
参数必须精确匹配
int(int,int)const
签名,包括可能的cv和ref限定符。

这是一个令人烦恼的难题,这不断导致语言提案,试图解决它(,)

在此之前,如何在类型上包装调用特定成员函数的问题相当困难,因为该类型的成员函数要么重载,要么是模板,要么采用默认参数

最简单的方法就是编写一个lambda:

[](A& a, auto&&... args) -> decltype(a.show(FWD(args)...)) { return a.show(FWD(args)...); }
但这实际上并不是那么容易,也不是特别方便——它实际上只处理在非
常量
a
上可调用
show
的情况。如果我们有
const
和非
const
重载会怎么样?或者
&
&

在我看来,实现这一点的最完整方法是使用:

在您的情况下,您需要:
CLASS\u成员(A,show)
。这将为您提供一个可以正确调用的函数对象:

auto show_fn = CLASS_MEMBER(A, show);
show_fn(a, 1);       // ok, calls a.show(1)
show_fn(a, 1, 2);    // ok, calls a.show(1, 2)
show_fn(a, 1, 2, 3); // error, no matching call - but sfinae friendly

你想让你的函数只接受带有特定签名的成员函数吗?@r3musn0x是的,它必须是成员函数,我知道我可以用lambdasy修复它你的函数
::show()
-如果你颠倒前两个参数,它是
std::invoke()
的专用版本,以防你想使用它。仅供参考。这实际上使它更加完整和通用的模板int-show(T&&obj,int(std::remove_-reference_-T::*Fn)(Args…)const,Args&&Args){return(obj.*Fn)(std::forward(Args…);}然后它适用于所有不同的情况
#define CLASS_MEMBER(T, mem) boost::hof::fix(boost::hof::first_of(\
    boost::hof::match(                                            \
        [](auto, T& s, auto&&... args)                            \
            BOOST_HOF_RETURNS(s.mem(FWD(args)...)),               \
        [](auto, T&& s, auto&&... args)                           \
            BOOST_HOF_RETURNS(std::move(s).mem(FWD(args)...)),    \
        [](auto, T const&& s, auto&&... args)                     \
            BOOST_HOF_RETURNS(std::move(s).mem(FWD(args)...)),    \
        [](auto, T const& s, auto&&... args)                      \
            BOOST_HOF_RETURNS(s.mem(FWD(args)...))),              \
    [](auto self, auto&& this_, auto&&... args)                   \
        BOOST_HOF_RETURNS(self(*FWD(this_), FWD(args)...))        \
    ))
auto show_fn = CLASS_MEMBER(A, show);
show_fn(a, 1);       // ok, calls a.show(1)
show_fn(a, 1, 2);    // ok, calls a.show(1, 2)
show_fn(a, 1, 2, 3); // error, no matching call - but sfinae friendly