Salut, j'aimerais savoir si il y a moyen de passer des références à un tuple et de les extraires : (Car ce code-ci marche bien mais, lorsque je veux utiliser des références le type de l'objet renvoyé par bind change, ce n'est plus un std::function mais un std::_BindHelper marchin quelque chose :
std::function<void(Ex&, std::string)> f1 = std::bind(&Ex::of, obj, "1");
Slot<void, std::function<void(Ex&, std::string)>> s1(f1);
s1(obj, "1");
//Ne marche pas!
std::function<void(Ex&, std::string&)> f2 = std::bind(&Ex::of, obj, "1");
Slot<void, std::function<void(Ex&, std::string&)>> s2(f2);
s2(obj, "1");
Alors j'ai essayer de créer mon propre binder et de faire ça :
#ifndef BIND_H
#define BIND_H
#include "function.h"
#include <tuple>
namespace sfgl {
namespace helper {
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
}
template <typename R> class Bind {
};
template <typename R, typename... A> class Bind <R(A...)> {
public :
Bind (R(*f)(A...) , A... args) : function(f) {
params = std::make_tuple(args...);
}
template<int ...S>
R operator ()(A... args) {
params = std::make_tuple(args...);
return callFunc(typename helper::gens<sizeof...(A)>::type());
}
template<int ...S>
R operator ()() {
//R(*func)(A...) = *reinterpret_cast<R**>(function);
return callFunc(typename helper::gens<sizeof...(A)>::type());
}
template<int ...S>
R callFunc(helper::seq<S...>)
{
return function(std::get<S>(params)...);
}
//private :
std::tuple <A...> params;
R(*function)(A...);
};
template <typename R, typename O, typename... A> class Bind <R(O&, A...)> {
public:
Bind (R(O::*f)(A...), O object, A... args) : object(object), function(f) {
params = std::make_tuple(args...);
}
void changeParams (A... args) {
params = std::make_tuple(args...);
}
R operator ()(A... args) {
params = std::make_tuple(args...);
return callFunc(typename helper::gens<sizeof...(A)>::type());
}
template<int ...S>
R operator ()() {
return callFunc(typename helper::gens<sizeof...(A)>::type());
}
template<int ...S>
R callFunc(helper::seq<S...>)
{
return (object.*function)(std::get<S>(params)...);
}
//private :
O object;
std::tuple <A...> params;
R(O::*function)(A...);
};
}
#endif // BIND
Malheureusement, ça ne fonctionne pas lorsque je veux passer des références à mon slot.
Je sais que il faut utiliser un std::reference_wrapper mais je ne vois pas comment l'utiliser avec les templates variadique..., afin de faire un tuple qui puisse stocker aussi bien des références que des pointeurs.
Bref le but final est d'essayer de faire un binder dont le type ne change pas (que ce soit lorsque j'utilise des références, ou bien des placeholders...)
Bind<void(Ex&, std::string)> b1 (&Ex::of,obj, _1);
Slot<void, Bind<void(Ex&, std::string)>> s1 (b1);
s1("1");
Bind<void(Ex&, std::string&)> b2 (&Ex::of,obj, _1);
Slot<void, Bind<void(Ex&, std::string)>> s2 (b2);
s2(std::ref("1"));
Mais je ne sais pas si c'est possible de faire quelque chose comme ça.
Au pire je mettrai des arguments bidons lors de la création de mon binder si j'en ai pas besoin lors de l'appel du slot que je remplacerai à l'appel du slot, et je n'auriserai pas le passage par référence qui me pose problème mais que par pointeur.