C++ 从成员函数签名自动推断lambda参数

C++ 从成员函数签名自动推断lambda参数,c++,c++11,C++,C++11,通常,我使用lambda函数为第三方库设置对成员函数的回调。例如: setCallback([this](auto&&…x){handleCallback(std::forward(x)…);}); 现在,我有一个带有重载函数的库来设置回调,这使得这一行不明确: #包括 #包括 类库 { 公众: typedef std::function IntFunction; typedef std::function IntIntFunction; void setCallback(intf函数){f_

通常,我使用lambda函数为第三方库设置对成员函数的回调。例如:

setCallback([this](auto&&…x){handleCallback(std::forward(x)…);});
现在,我有一个带有重载函数的库来设置回调,这使得这一行不明确:

#包括
#包括
类库
{
公众:
typedef std::function IntFunction;
typedef std::function IntIntFunction;
void setCallback(intf函数){f_int=f;}
void setCallback(IntIntFunction f){f_int_int=f;}
void callCallback(int a,int b){
if(f_int_)f_int_(a);
if(f_int_int_)f_int_int_(a,b);
}
私人:
int函数f_int_;
初始化函数f_int_int;
};
类MyClass
{
公众:
MyClass(){
//setCallback([this](auto&&…x){handleCallback(std::forward(x)…);});
lib.setCallback([this](inta,intb){handleCallback(a,b);});
}
无效handleCallback(内部a、内部b){

std::cout您可以为此创建函数:

class MyClass
{
    template <typename Ret, typename ...Args>
    void setCallback(Ret (MyClass::*member)(Args...) /*const*/) {
        lib.setCallback([=](Args...args)
            {
                (this->*member)(std::forward<decltype(args)>(args)...);
            });
    }

public:
    MyClass() { setCallback(&MyClass::handleCallback); }

    void handleCallback(int a, int b) {
        std::cout << "handleCallback: " << a << ", " << b << std::endl;
    }

    Library lib;
};
class-MyClass
{
模板
void setCallback(Ret(MyClass::*成员)(Args…/*const*/){
lib.setCallback([=](Args…Args)
{
(此->*成员)(标准:转发(args)…);
});
}
公众:
MyClass(){setCallback(&MyClass::handleCallback);}
无效handleCallback(内部a、内部b){

std::cout诀窍是正确地提升函数,尤其是返回类型表达式,因为它将启用SFINAE,使得
std::function
构造函数能够检测lambda是否能够被调用:

lib.setCallback([this](auto&& ...x) -> 
    decltype(void(handleCallback(std::forward<decltype(x)>(x)...))) {
        handleCallback(std::forward<decltype(x)>(x)...);
    }
);
然后像这样使用它:

lib.setCallback([this](auto&& ...x) RETURNS(handleCallback(std::forward<decltype(x)>(x)...)));
lib.setCallback([this](auto&&…x)返回(handleCallback(std::forward(x)…));

根据给定的答案,我构造了这个函数:

#包括
#包括
模板
自动获取lambda(TClass*实例,TRet(TClass::*成员)(Args…)
{
如果constexpr(std::is_void::value)
返回[=](Args…Args){(实例->*成员)(std::forward(Args)…);};
其他的
return[=](Args…Args){return(实例->*成员)(std::forward(Args)…);};
}
它可以这样使用:

lib.setCallback(getLambda(this,&MyClass::handleCallback));


现在我用它来替换我以前使用过的lambda函数(如问题中所示)因为它提高了可读性。

你的问题不清楚。这里只显示了一个
handleCallback
函数,所以这里没有什么可以推断的。它是关于
setCallback
函数的。在我注释掉的那行中,编译器无法推断
auto
。这与重载无关。这根本无效C++:这不是可变参数包的工作原理。基本上,任何时候你都有<代码>……< < /代码>(或<代码>某物…<代码>,或其中的一些变体),必须用这么多的话来描述“模板”。在附近的某个地方。它在哪里,在这里?如果你删除一个
setCallback
函数,它就可以工作:@SamVarshavchik通用lambda在它的参数列表中引入参数包。我在lambda之外没有看到任何
。我真的很喜欢这种方法,因为它避免了在意图是不过,我还是接受了Jarod42的答案,因为这里还有一个重复的
handleCallback
#define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) \
    -> decltype((__VA_ARGS__)) {                         \
        return __VA_ARGS__;                              \
    }
lib.setCallback([this](auto&& ...x) RETURNS(handleCallback(std::forward<decltype(x)>(x)...)));