Utiliser std::forward deux fois ?
Bonjour,
Je suis dans le cas (simplifié) suivant :
Code:
1 2 3 4 5 6 7 8
| template<typename F1, typename F2, typename ... Args>
std::pair<std::function<void()>, std::function<void()>>
do_bind(F1&& f1, F2&& f2, Args&& ... args) {
return make_pair(
std::bind(std::forward<F1>(f1), std::forward<Args>(args)...),
std::bind(std::forward<F2>(f2), std::forward<Args>(args)...)
);
} |
Je ne maîtrise pas encore totalement la sémantique de mouvement, mais j'ai peur que ce code ne fonctionne pas comme je le voudrais : d'après moi, les arguments sont "déplacés" pour le premier bind, il ne sont alors plus disponibles pour le second.
On peut le tester avec ce code :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| struct A {
int i = 0;
A() = default;
A(int i) : i(i) {}
A(const A& a) : i(a.i) {}
A(A&& a) : i(a.i) { a.i = 0; }
};
void some_func(const A& a) { std::cout << a.i << std::endl; }
void some_other_func(const A& a) { std::cout << a.i << std::endl; }
int main() {
auto ret = do_bind(&some_func, &some_other_func, A(5));
ret.first();
ret.second();
} |
... qui affiche 0 et 5, suggérant que le second membre de la paire a été initialisé en premier.
Ma question est donc :
- que faut-il faire pour que les deux fonctions ainsi créées reçoivent toutes deux des arguments aussi bien "forwardés" que possible?
- quels sont les inconvénients de cette approche :
Code:
1 2 3 4 5 6 7
| template<typename F1, typename F2, typename ... Args>
std::pair<std::function<void()>, std::function<void()>>
do_bind(F1&& f1, F2&& f2, Args&& ... args) {
auto fb1 = std::bind(std::forward<F1>(f1), args...);
auto fb2 = std::bind(std::forward<F2>(f2), std::forward<Args>(args)...);
return make_pair(std::move(fb1), std::move(fb2));
} |
Je précise qu'un des buts de cette fonction est d'éviter à son utilisateur d'avoir à fournir deux fois une même série d'arguments.