如何返回使用参数包定义的成员函数的 std::function 对象?
Posted
技术标签:
【中文标题】如何返回使用参数包定义的成员函数的 std::function 对象?【英文标题】:How to return a std::function object of member function which define with parameter packs? 【发布时间】:2019-11-15 17:21:47 【问题描述】:我想定义一个成员函数,它可以返回另一个成员函数的std::function
对象。一般来说,这很容易。但是如果那个成员函数是由参数包定义的,我就不知道怎么做了。
我写了一些代码如下,
class Example
public:
template<typename... Args>
double getSome(Args... args)
// do something
template<typename... Args>
std::function<double(Args...)> getSomeFun()
return std::bind(&Example::getSome<Args...>, this);
;
这看起来是正确的,不幸的是。当我在main()
方法中调用getSetArgsFunction()
时,我得到了很多错误信息。在main()
方法,我的代码如下,
int main()
Example e;
e.getSomeFun()(1.0, 2.0, 3.0);
我尝试编译它,但是gcc
打印一些错误如下,
error: no match for call to ‘(std::function<double()>) (double, double, double)’
那么,我们应该怎么做呢?
更新
感谢@Quentin,但他/她的建议也无法解决问题。 完整且最小的示例代码为:
#include <functional>
#include <iostream>
class Example
public:
template<typename... Args>
double getSome(Args... args)
for (auto x : args...)
std::cout << x << '\n';
template<typename... Args>
std::function<double(Args...)> getSomeFun()
return std::bind(&Example::getSome<Args...>, this);
;
int main()
Example e;
e.getSomeFun<double, double, double>()(1.0, 2.0, 3.0);
错误信息是:
In file included from test2.cpp:14:0:
/usr/include/c++/7/functional: In instantiation of ‘struct std::_Bind_check_arity<double (Example::*)(double, double, double), Example*>’:
/usr/include/c++/7/functional:854:12: required from ‘struct std::_Bind_helper<false, double (Example::*)(double, double, double), Example*>’
/usr/include/c++/7/functional:875:5: required by substitution of ‘template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) [with _Func = double (Example::*)(double, double, double); _BoundArgs = Example*]’
test2.cpp:29:25: required from ‘std::function<double(Args ...)> Example::getSomeFun() [with Args = double, double, double]’
test2.cpp:36:40: required from here
/usr/include/c++/7/functional:841:7: error: static assertion failed: Wrong number of arguments for pointer-to-member
static_assert(_Varargs::value
^~~~~~~~~~~~~
test2.cpp: In instantiation of ‘std::function<double(Args ...)> Example::getSomeFun() [with Args = double, double, double]’:
test2.cpp:36:40: required from here
test2.cpp:29:58: error: could not convert ‘std::bind(_Func&&, _BoundArgs&& ...) [with _Func = double (Example::*)(double, double, double); _BoundArgs = Example*; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind<double (Example::*(Example*))(double, double, double)>](((Example*)this))’ from ‘std::_Bind_helper<false, double (Example::*)(double, double, double), Example*>::type aka std::_Bind<double (Example::*(Example*))(double, double, double)>’ to ‘std::function<double(double, double, double)
’
return std::bind(&Example::getSome<Args...>, this);
【问题讨论】:
您的声明要求调用为e.getSomeFun<double, double, double>()(1.0, 2.0, 3.0);
。你想推迟创建包直到它可以从你称之为std::function
的3个doubles
中推断出来吗?
你总是要立即调用getSomeFun
返回的函数对象吗?如果是这样,为什么这个返回函数的中间步骤?如果不是,也许您可以重写您的示例,以便调用与getSomeFun
的调用不在同一个表达式中? (此外,您可能想尝试编译您发布的代码以消除拼写错误。在线编译器可能对此很有用;C++ tag info page 上有在线编译器列表。)
谢谢,我更新了代码和错误信息。
【参考方案1】:
使用绑定,您需要放置占位符参数:
std::bind(&Example::getSome<Args...>, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3
);
您需要放置的占位符数量等于您的函数所需的参数数量。
我建议在这种情况下使用 lambda,因为可变参数占位符不是一个东西:
template<typename... Args>
std::function<double(Args...)> getSomeFun()
return [this](Args... args)
return getSome(args...);
;
此外,如果您可以在调用站点构建std::function
,则可以使用推导函数返回类型来消除调用位置的std::function
开销,并且不需要std::function
:
template<typename... Args>
auto getSomeFun()
return [this](Args... args)
return getSome(args...);
;
【讨论】:
以上是关于如何返回使用参数包定义的成员函数的 std::function 对象?的主要内容,如果未能解决你的问题,请参考以下文章