Std :: bind and impeccable shipment

The following code does not compile:

#include <functional> template<class ...Args> void invoke(Args&&... args) { } template<class ...Args> void bind_and_forward(Args&&... args) { auto binder = std::bind(&invoke<Args...>, std::forward<Args>(args)...); binder(); } int main() { int a = 1; bind_and_forward(a, 2); } 

If I understand correctly, the reason is this: std::bind copies its arguments, and when binder operator() is called, it passes all related arguments as lvalues ​​- even those that enter bind as rvalues. But invoke was created for the original arguments and cannot accept what the binder trying to pass.

Is there any solution to this problem?

+5
source share
1 answer

Your understanding is correct - bind copies its arguments. Thus, you must ensure that invoke() properly overloaded, which will be called on lvalues:

 template<class ...Args> void bind_and_forward(Args&&... args) { auto binder = std::bind(&invoke<Args&...>, std::forward<Args>(args)...); ^^^^^^^^ binder(); } 

This works for most types. There are a few exceptions listed in [func.bind.bind] for operator() , where Arg& not enough. One of the ones you specify is std::reference_wrapper<T> . We can get around this by replacing the use of Args& above with a type of type. Typically, we just add an lvalue link, but for reference_wrapper<T> we just want T& :

 template <typename Arg> struct invoke_type : std::add_lvalue_reference<Arg> { }; template <typename T> struct invoke_type<std::reference_wrapper<T>> { using type = T&; }; template <typename T> using invoke_type_t = typename invoke_type<T>::type; 

Paste this back into the original solution, and we get something that works for reference_wrapper :

 template<class ...Args> void bind_and_forward(Args&&... args) { auto binder = std::bind(&invoke<invoke_type_t<Args>...>, // ^^^^^^^^^^^^^^^^^^^ std::forward<Args>(args)...); binder(); } 

Of course, if one of Arg is a placeholder, it still won't work. And if it's a binding expression, you will also have to write something else.

+5
source

All Articles