在深入修复活页夹之前,请注意以下几点:
- 你真的不需要使用as
std::mem_fn()
的第一个参数,std::bind()
因为std::bind()
已经知道如何处理成员函数指针。
- 获取成员函数地址的类型未定义。也就是说,你不能真正
std::string::push_back
成为一个只接受一个参数的成员函数指针。
- 而不是使用
std::ref(testobj)
你可以 juse &testobj
。
如果它需要有参数,你不能推导出这样的成员函数:你需要指定参数:
template <class T, typename RETURN_TYPE, typename...Args, typename... Arguments>
std::function<RETURN_TYPE(Arguments...)>
obj_bind(RETURN_TYPE (T::*in_fun)(Args...), T & obj, Arguments... params) {
...
}
这可以帮助您克服直接错误。下一个问题是您以某种方式将绑定参数与被调用的函数类型相关联。当然,这不是它的工作原理。在您的情况下,结果参数实际上不带任何参数,即,您将有这样的声明:
template <class T, typename RETURN_TYPE, typename... Args, typename... Arguments>
std::function<RETURN_TYPE()>
obj_bind(RETURN_TYPE (T::*in_fun)(Args...), T & obj, Arguments... params) {
...
}
如果您实际上在函数中使用了占位符,则返回的std::function<RC(...)>
实际上会带有一些参数。弄清楚这些论点有点不重要。但是,当将参数类型限制为指向函数的指针或指向成员函数的指针时,应该可以返回适当的函数对象。
只是为了好玩,这里是一个似乎处理占位符的实现(虽然它没有经过彻底测试):
#include <functional>
#include <iostream>
#include <string>
using namespace std::placeholders;
struct foo
{
void f(int i, double d, char c) {
std::cout << "f(int=" << i << ", double=" << d << ", char=" << c << ")\n";
}
};
template <typename...> struct type_list;
template <typename, typename, typename, typename> struct objbind_result_type;
template <typename RC, typename... RA>
struct objbind_result_type<RC, type_list<RA...>, type_list<>, type_list<> > {
typedef std::function<RC(RA...)> type;
};
template <typename RC,
typename... RA,
typename A0, typename... A,
typename B0, typename... B>
struct objbind_result_type<RC, type_list<RA...>,
type_list<A0, A...>,
type_list<B0, B...> >;
template <bool, typename, typename, typename, typename, typename>
struct objbind_result_type_helper;
template <typename A0, typename RC, typename... RA, typename... A, typename...B>
struct objbind_result_type_helper<true, A0, RC, type_list<RA...>, type_list<A...>, type_list<B...> > {
typedef typename objbind_result_type<RC, type_list<RA..., A0>, type_list<A...>, type_list<B...> >::type type;
};
template <typename A0, typename RC, typename... RA, typename... A, typename...B>
struct objbind_result_type_helper<false, A0, RC, type_list<RA...>, type_list<A...>, type_list<B...> > {
typedef typename objbind_result_type<RC, type_list<RA...>, type_list<A...>, type_list<B...> >::type type;
};
template <typename RC,
typename... RA,
typename A0, typename... A,
typename B0, typename... B>
struct objbind_result_type<RC, type_list<RA...>,
type_list<A0, A...>,
type_list<B0, B...> > {
typedef typename objbind_result_type_helper<bool(std::is_placeholder<B0>::value), A0,
RC, type_list<RA...>,
type_list<A...>,
type_list<B...> >::type type;
};
// This is the function I'd like to have working:
template <class T, typename RETURN_TYPE, typename...Args, typename... Arguments>
typename objbind_result_type<RETURN_TYPE, type_list<>, type_list<Args...>, type_list<Arguments...> >::type
obj_bind(RETURN_TYPE (T::*in_fun)(Args...), T & obj, Arguments... params)
{
return std::bind(in_fun, &obj, params...);
}
int main()
{
foo fo;
auto fun = obj_bind(&foo::f, fo, _1, 2.34, _2);
fun(17, 'b');
}