Прежде чем приступить к ремонту переплета, несколько замечаний:
- Вам действительно не нужно использовать
std::mem_fn()
для первого аргумента std::bind()
, так как std::bind()
уже знает, как обращаться с указателями на функции-члены.
- Тип получения адреса функции-члена не определен. То есть вы не можете на самом деле
std::string::push_back
быть указателем функции-члена, принимающим только один аргумент.
- Вместо использования
std::ref(testobj)
вы можете использовать только &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) {
...
}
Это избавит вас от непосредственной ошибки. Следующая проблема заключается в том, что вы каким-то образом связали аргументы bound с типом вызываемой функции. Конечно, это не так. В вашем случае результирующий аргумент фактически не принимает никаких аргументов, т. е. у вас будет такое объявление:
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');
}
person
Dietmar Kühl
schedule
07.12.2014
std::bind
вам не нуженstd::mem_fn
. - person Stephan Dollberg   schedule 08.12.2014obj_bind
существенно отличается отstd::bind()
? Вы можете просто сделатьstd::bind(&string::push_back, test_obj, 'C')
, нет? - person Barry   schedule 08.12.2014std::bind
не требуетstd::mem_fn
. Это сильно упростит меня. Что касается отличий отstd::bind
:std::ref
по-прежнему необходим для привязки к ссылке целевого объекта. - person Charles Ofria   schedule 08.12.2014std::bind(&string::push_back, &test_obj, 'C')
будет более близким аналогом, использование&test_obj
эквивалентноstd::ref(test_obj)
для этой цели, это заставляетbind
ссылаться на исходный объект, а не копировать его. - person Jonathan Wakely   schedule 08.12.2014