For a Packaged_Task implementation in C++11
i want to achieve what i've expressed in C++14 Code below. In other words i want to forward into a lambda expression.
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = [f = std::forward<F>(f)]() mutable { return std::move(f); };
///...
I'm aware of workarounds for moving into a lambda (but unfortenately this workarounds need a default constructible Object, in my case the object is most often a lambda expression without default-constructor)
How about creating a wrapper struct which does a move during copy construction:(. (I know that's bad, makes me remember of auto_ptr)
template <typename F>
struct Wrapped {
using Ftype = typename std::remove_reference<F>::type;
Wrapped(Ftype&& f): f_(std::move(f)) {}
Wrapped(const Wrapped& o): f_(std::move(o.f_)) {}
mutable Ftype f_;
};
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
Wrapped<std::remove_reference<decltype(f)>::type> wrap(std::forward<F>(f));
auto f_holder = [wrap]() mutable { return std::move(wrap.f_); };
This is just a rough idea. Not compiled or tested.
NOTE: I have seen this technique before, do not remember whether it was on SO itself or on some blog.
First, let's boil down the question to its core: the function object is somewhat of a distraction. Essentially, you want to be able to create a lambda with a capture holding a move-only object. In C++11 that isn't directly supported which gave raise to the C++14 approach of allowing specification of how the capture is build.
For C++11 it is necessary to use a copy. Since the underlying type doesn't support copying, it become necessary to actually move the object instead of copying it. Doing so can be achieved by a suitable wrapper defining a copy constructor not really copying but rather moving. Here is an example showing that:
#include <utility>
struct foo {
foo(int) {}
foo(foo&&) = default;
foo(foo const&) = delete;
};
template <typename T>
class move_copy
{
T object;
public:
move_copy(T&& object): object(std::move(object)) {}
move_copy(move_copy& other): object(std::move(other.object)) {}
T extract() { return std::forward<T>(this->object); }
};
template <typename T>
void package(T&& object)
{
move_copy<T> mc(std::forward<T>(object));
foo g = [mc]() mutable { return mc.extract(); }();
}
int main()
{
foo f(0);
package(std::move(f));
}
The move_copy<T> wrapper actually just captures the argument the way it is passed: if an lvalue is being passed in, an lvalue is captured. To properly get hold of the contained object, the extract() member std::forward<T>()s the object: the function can be called only once safely as an object is potentially moved from there.
Breaking copy semantics by making it a move is a bad idea. If it was the only option, go for it, but it is not.
Instead, we can pass the moved value in as an argument to the lambda, and move it into the wrapping code.
curry_apply takes some value and a function object, and returns that function object with the value bound to the first argument.
template<class T, class F>
struct curry_apply_t {
T t;
F f;
template<class...Args>
auto operator()(Args&&...args)
-> typename std::result_of_t<F&(T&, Args...)>::type
{
return f(t, std::forward<Args>(args)...);
}
};
template<class T, class F>
curry_apply_t<typename std::decay<T>::type, typename std::decay<F>::type>
curry_apply( T&& t, F&& f ) {
return {std::forward<T>(t), std::forward<F>(f)};
}
Use:
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = curry_apply(
std::move(_future),
[](Future<R>& f) mutable { return std::move(f); };
);
basically we store the moved-in data outside of the lambda in a manually written function object. We then pass it in as an lvalue argument at the front of the lambda's argument list.
Here is a more complex version of the same solution.
Related
As I understand, typedef cannot be used for overloading but what if I need to use some different types as arguments to the function pointer?
How can I make it work with the following functionality?
{
public:
typedef void (*InitFunc)(float x);
typedef void (*InitFunc)(int a, char b); //Needs to be added
virtual void initialize(InitFunc init) = 0;
};
Edit:
I cannot use C++17, so can't use variant
As commented, the easiest way is a union, although not very type safe and C++-y. Here is an example with inheritance, since you commented that you want inheritance.
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
union InitFn {
FloatInit fi;
IntCharInit ici;
};
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
f.fi(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
As mentioned by other commenters, you can use std::variant to enhance type safety and get rid of the manual union definition:
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
typedef std::variant<FloatInit, IntCharInit> InitFn;
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
std::get<FloatInit>(f)(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
One solution is to create a simple wrapper class template instead, to allow the compiler to automatically generate instantiations as necessary. This is relatively simple if init is always guaranteed to be a non-member function (and by extension, an actual function and not a functor/lambda).
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> {
public:
// Supply component types if needed.
// Tuple used for params, for convenience.
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
// Create from pointer or reference.
constexpr InitFunc(func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator func_ptr_type() { return ptr; }
operator func_ref_type() { return *ptr; }
private:
// Actual function pointer.
func_ptr_type ptr;
};
// And a nice, clean creator, which can be renamed as necessary.
template<typename Init>
constexpr auto make(Init func) { return InitFunc<Init>(func); }
This creates a nice little wrapper that can easily be optimised out entirely, and will compile as long as C++14 support is available.
Note that you require a C++11 compiler (or variadic templates, rvalue references, perfect forwarding, and constexpr support) at the absolute minimum, and will need to modify make() to have a trailing return type for pre-C++14 compilers. I believe this is compatible with C++11 constexpr, but I'm not 100% sure.
If you want InitFunc to be able to accept pointers/references-to-member-function (including functors and lambdas), you'll need to provide an additional version to isolate it into a non-member "function", and likely bind it to a class instance. It may be worth looking into std::bind() in this case, although I'm not sure if it has any overhead.
In this case, I would suggest splitting the member types off into a base class, to reduce the amount of code you'll need to duplicate.
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
// Supply component types if needed.
// Tuple used for params, for convenience.
// Using actual function type as a base, similar to std::function.
template<typename Ret, typename... Params>
class InitFunc<Ret(Params...)> {
public:
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
};
// Non-member functions.
// As member types are now dependent types, we qualify them and use `typename`.
// Yes, it looks just as silly as you think it does.
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> : public InitFunc<Ret(Params...)> {
// Actual function pointer.
typename InitFunc::func_ptr_type ptr;
public:
// Create from pointer or reference.
constexpr InitFunc(typename InitFunc::func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(typename InitFunc::func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr typename InitFunc::return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator typename InitFunc::func_ptr_type() { return ptr; }
operator typename InitFunc::func_ref_type() { return *ptr; }
};
// See ecatmur's http://stackoverflow.com/a/13359520/5386374 for how to accomodate member functions.
// ...
// Non-member function make() is unaffected.
// An overload will likely be needed for member functions.
template<typename Init>
auto make(Init func) { return InitFunc<Init>(func); }
Despite the awkwardness inside our derived specialisation, any code that relies on InitFunc shouldn't (to my knowledge) see any changes to its API; the previous example will work just fine if we swap to this new InitFunc, and be none the wiser after recompilation.
Note that it will change the ABI, though, and thus any code compiled for the simpler InitFunc will need to be recompiled for this version.
I recently came across a situation where I ended up with a large number of nested lambdas to build asynchronous computation chains.
template <typename F>
struct node : F
{
node(F&& f) : F{std::move(f)}
{
}
template <typename FThen>
auto then(FThen&& f_then)
{
return ::node{[p = std::move(*this), t = std::move(f_then)]()
{
}};
}
};
int main()
{
auto f = node{[]{ }}.then([]{ }).then([]{ });
return sizeof(f);
}
All the objects I capture in my the lambdas are empty, yet the size of the final object is greater than one: example on gcc.godbolt.org.
If I change the lambda inside node</* ... */>::then to a function object with explicit EBO, the size of the final object becomes one.
template <typename P, typename T>
struct node_lambda : P, T
{
node_lambda(P&& p, T&& t) : P{std::move(p)}, T{std::move(t)}
{
}
void operator()()
{
}
};
template <typename FThen>
auto node</* ... */>::then(FThen&& f_then)
{
return ::node{node_lambda{std::move(*this), std::move(f_then)}};
}
Live example on gcc.godbolt.org
I find this really annoying because I'm forced to either:
Write a lot of boilerplate code that is roughly equivalent to the lambda.
Pay an additional memory cost due to the fact that something like EBO doesn't apply to lambda captures.
Is there anything in the Standard that explicitly forces empty lambda captures to take additional space? If so, why?
From expr.prim.lambda.capture:
For each entity captured by copy, an unnamed non-static data member is declared in the closure type.
While the lambdas here have no capture:
auto f = node{[]{ }}.then([]{ }).then([]{ });
and hence have no unnamed non-static data members, and hence are empty, that's not what then() actually uses. It uses this:
return ::node{[p = std::move(*this), t = std::move(f_then)](){}};
that lambda captures t and p by copy, and hence has two unnamed non-static data members. Each .then() adds another member variable, even if each one is empty, hence the size of the node keeps going up.
Or in other words, the empty base optimization only applies to bases, and capture for lambdas doesn't create bases, it creates non-static data members.
The other answers have the cause, so I will not re-iterate. I will just add that I was able to turn your example into an inheritance based one without too much boilerplate. Since you do public inheritance in the OP, I opted to remove the c'tor and go for aggregate initialization.
It only required two deduction guides to make the code almost as pretty as your original scheme:
Live on Coliru
#include <utility>
#include <iostream>
struct empty {
void operator()() {}
};
template <typename P, typename T>
struct node : P, T
{
template <typename FThen>
auto then(FThen&& f_then)
{
return ::node{std::move(*this), std::forward<FThen>(f_then)};
}
void operator()() {
P::operator()();
T::operator()();
}
};
template <typename P> node(P) -> node<P, ::empty>;
template <typename P, typename T> node(P, T) -> node<P, T>;
int main()
{
auto f = node{[]{ }}.then([]{ }).then([]{ });
std::cout << sizeof(f);
}
The EBO was applied, as you can see by following the link.
BTW, since we are are moving *this, it may be worth to r-value qualify node::then. Just to avoid any nastiness.
Given the as-if rule and [expr.prim.lambda.closure]/2:
An implementation may define the closure type differently from what is
described below provided this does not alter the observable behavior
of the program other than by changing:
the size and/or alignment of the closure type,
whether the closure type is trivially copyable (Clause [class]),
whether the closure type is a standard-layout class (Clause [class]), or
whether the closure type is a POD class (Clause [class]).
I don't see anything preventing an implementation from using some kind of magic to optimize away the storage for the captured empty variable.
That said, doing so would be an ABI break, so don't hold your breath.
Allowing - or requiring - an implementation to make the type of a captured empty variable a base of the closure type, on the other hand, would be a horrendously bad idea. Consider:
struct X { };
struct Y { };
void meow(X x); // #1
void meow(Y y); // #2
void meow(std::function<void()> f); // #3
template<class T, class U>
void purr(T t, U u) {
meow([t = std::move(t), u = std::move(u)] { /* ... */ });
}
It would be insane for purr to do anything other than call #3, yet if captures can become bases then it can call #1, or #2, or be ambiguous.
As others have noted, lambdas are specified to capture as member variables not as bases. So you are out of luck.
What you could do is take a page from bind.
Suppose you have a tuple that does use empty base optimization. Then we can write a helper:
template<class Sig>
struct lambda_ebo_t;
template<class F, class...Args>
struct lambda_ebo_t<F(Args...)>:
private std::tuple<Args...>,
private F
{
decltype(auto) operator()(){
return std::apply( (F&)*this, (std::tuple<Args...>&)*this );
}
template<class...Ts>
lambda_ebo_t( F f, Ts&&...ts ):
std::tuple<Args...>( std::forward<Ts>(ts)... ),
F( std::move(f) )
{}
};
template<class F, class...Args>
lambda_ebo_t<F, std::decay_t<Args>...>
lambda_ebo( F f, Args&&...args ) {
return {std::move(f), std::forward<Args>(args)...};
}
That is a bunch of boilerplate, and incomplete (reference capture may not work right even if you use std::ref), but it gives us:
template <typename FThen>
auto then(FThen&& f_then)
{
return ::node{lambda_ebo([](auto&& p, auto&& t)
{
}, std::move(*this), std::move(f_then))};
}
where we store the data outside the lambda and pass it in as arguments to the lambda. The storage uses EBO.
No need to write a custom EBO class for each lambda, just a few hoops to jump through when you need a lambda with EBO enabled.
This is one without using the tuple, but it doesn't support fundamantal types like int or other things you cannot derive from:
template<class Sig>
struct lambda_ebo_t;
template<class F, class...Args>
struct lambda_ebo_t<F(Args...)>:
private Args...,
// private std::tuple<Args...>,
private F
{
decltype(auto) operator()(){
//return std::apply( (F&)*this, (std::tuple<Args...>&)*this );
return ((F&)(*this))((Args&)*this...);
}
template<class...Ts>
lambda_ebo_t( F f, Ts&&...ts ):
Args(std::forward<Ts>(ts))...,
F( std::move(f) )
{}
};
template<class F, class...Args>
lambda_ebo_t<F(std::decay_t<Args>...)>
lambda_ebo( F f, Args&&...args ) {
return {std::move(f), std::forward<Args>(args)...};
}
Live example, with this test code:
auto test = lambda_ebo( [](auto&&...args){std::cout << sizeof...(args) << "\n";}, []{} , []{}, []{}, []{}, []{}, []{}, []{}, []{}); //
std::cout << "bytes:" << sizeof(test) << "\n";
std::cout << "args:";
test();
sizeof(test) is 1, and it "captures" 8 arguments.
Empty base optimization works for me in the following case
#include <utility>
template <typename F>
class Something : public F {
public:
Something(F&& f_in) : F{std::move(f_in)} {}
};
int main() {
auto something = Something{[]{}};
static_assert(sizeof(decltype(something)) == 1);
}
Live example here https://wandbox.org/permlink/J4m4epDUs19kp5CH
My guess is that the reason it's not working in your case is that the lambda you use in the then() method is not actually empty, it has member variables - the ones listed in your capture. So there is no real empty base there.
If you change the last line of your code to just return node{[]{}} then it works. The lambdas used by .then() do not materialize as "empty" classes.
Whereas in the explicit struct case, it has no member variables per se, only classes it derives from, hence empty base optimization can work there.
I have the following api:
old_operation(stream, format, varArgs);
And I want to write an adaptor to make it possible to write the call as follows:
stream << operation(format, varArgs);
To do this I'm using a temporary object which stores references to varArgs and overload the operator<< to apply the old_operation() as follows:
template<typename ...T>
decltype(auto) storage(T&& ...t) {
return [&](auto&& f) ->decltype(auto) {
return std::forward<decltype(f)>(f)(t...);
};
}
template<typename ...T>
class Operation
{
using Storage = decltype(storage(std::declval<T>()...));
public:
template<typename ...Args>
explicit Operation(Args&& ...args) :
mArgs(storage(std::forward<Args>(args)...)) {};
template<class StreamType>
StreamType& Apply(StreamType& stream)
{
auto f = [&](auto&& ...xs)
{
old_operation(stream, std::forward<decltype(xs)>(xs)...);
}
mArgs(f);
return stream;
}
private:
Storage mArgs;
};
template<typename ...Args>
Operation<Args...> MakeOperation(Args&&... args)
{
return Operation<Args...>(std::forward<Args>(args)...);
}
template<class StreamType, typename ...Args>
StreamType& operator<<(StreamType& stream, Operation<Args...>&& operation)
{
return operation.Apply(stream);
}
This works great but now I need to add some using namespace declarations embedded into the operation call:
let's say I have
namespace X {namespace Y { namespace Z { int formater(double x) { return std::round(x); }}}
And I don't want to add all the namespaces for this call, so I'm doing something like:
#define OPERATION(...) \
[&]() { \
using namespace ::X:Y:Z; \
return Operation("" __VA_ARGS__); }() \
which allows me to do:
stream << OPERATION(format, formater(2.3));
The problem with the lambda is that the temporaries are being created in a different scope than the Apply() call, which is UB.
I don't know if by adding a const qualifier to mArgs it will prolong the life of the captured references as mentioned here. I'm not sure if this applies, I'm assuming they are stack-based references and that by adding the const qualifier to mArgs the qualifier is going to be applied to the captured references.
template<typename ...T>
decltype(auto) storage(T&& ...t) {
return [&](auto&& f) ->decltype(auto) {
return std::forward<decltype(f)>(f)(t...);
};
}
this is a haskell-style functor (well, a variardic one, which isn't very haskell). It takes Ts... and returns a function of type ((Ts...)->U)->U, ie that knows how to evaluate a function on the arguments you passed to it. This makes storage of type (Ts...)->( ((Ts...)->U)->U ) for a bit of algebraic fun.
I suspect your problem is that you have temporaries that you don't store. Generally not storing temporaries passed to a function, where the return value depends on the lifetime of those temporaries, results in fragile code.
If you have C++1z experimental::apply we can do this:
template<class... Ts>
decltype(auto) storage(Ts&&... ts) {
return
[tup=std::tuple<Ts...>(std::forward<Ts>(ts)...)]
(auto&& f)
->decltype(auto) mutable
{
return std::experimental::apply(decltype(f)(f), std::move(tup));
};
}
which returns a one-shot delayed call to std::apply. Apply takes a function and a tuple, and passes the arguments of the tuple to the function. It handles reference and r/lvalue-ness properly. Meanwhile, the container of the tuple makes the capture simpler, and lets us easily conditionally store rvalues while keeping lvalues as references.
I think this solves your problem, as temporaries get moved-into the tuple instead of being captured by reference, while non-temporaries are stored by reference.
There should be std::experimental::apply implementations that are better than anything I can sketch here available easily.
I'd like to create a function that takes a weak pointer and any kind of functor (lambda, std::function, whatever) and returns a new functor that only executes the original functor when the pointer was not removed in the meantime (so let's assume there is a WeakPointer type with such semantics). This should all work for any functor without having to specify explicitly the functor signature through template parameters or a cast.
EDIT:
Some commenters have pointed out that std::function - which I used in my approach - might not be needed at all and neither might the lambda (though in my original question I also forgot to mention that I need to capture the weak pointer parameter), so any alternative solution that solves the general problem is of course is also highly appreciated, maybe I didn't think enough outside the box and was to focused on using a lambda + std::function. In any case, here goes what I tried so far:
template<typename... ArgumentTypes>
inline std::function<void(ArgumentTypes...)> wrap(WeakPointer pWeakPointer, const std::function<void(ArgumentTypes...)>&& fun)
{
return [=] (ArgumentTypes... args)
{
if(pWeakPointer)
{
fun(args...);
}
};
}
This works well without having to explicitly specify the argument types if I pass an std::function, but fails if I pass a lambda expression. I guess this because the std::function constructor ambiguity as asked in this question. In any case, I tried the following helper to be able to capture any kind of function:
template<typename F, typename... ArgumentTypes>
inline function<void(ArgumentTypes...)> wrap(WeakPointer pWeakPointer, const F&& fun)
{
return wrap(pWeakPointer, std::function<void(ArgumentTypes...)>(fun));
}
This now works for lambdas that don't have parameters but fails for other ones, since it always instantiates ArgumentTypes... with an empty set.
I can think of two solution to the problem, but didn't manage to implement either of them:
Make sure that the correct std::function (or another Functor helper type) is created for a lambda, i.e. that a lambda with signature R(T1) results in a std::function(R(T1)) so that the ArgumentTypes... will be correctly deduced
Do not put the ArgumentTypes... as a template parameter instead have some other way (boost?) to get the argument pack from the lambda/functor, so I could do something like this:
-
template<typename F>
inline auto wrap(WeakPointer pWeakPointer, const F&& fun) -> std::function<void(arg_pack_from_functor(fun))>
{
return wrap(pWeakPointer, std::function<void(arg_pack_from_functor(fun))(fun));
}
You don't have to use a lambda.
#include <iostream>
#include <type_traits>
template <typename F>
struct Wrapper {
F f;
template <typename... T>
auto operator()(T&&... args) -> typename std::result_of<F(T...)>::type {
std::cout << "calling f with " << sizeof...(args) << " arguments.\n";
return f(std::forward<T>(args)...);
}
};
template <typename F>
Wrapper<F> wrap(F&& f) {
return {std::forward<F>(f)};
}
int main() {
auto f = wrap([](int x, int y) { return x + y; });
std::cout << f(2, 3) << std::endl;
return 0;
}
Assuming the weak pointer takes the place of the first argument, here's how I would do it with a generic lambda (with move captures) and if C++ would allow me to return such a lambda:
template<typename Functor, typename Arg, typename... Args>
auto wrap(Functor&& functor, Arg&& arg)
{
return [functor = std::forward<Functor>(functor)
, arg = std::forward<Arg>(arg)]<typename... Rest>(Rest&&... rest)
{
if(auto e = arg.lock()) {
return functor(*e, std::forward<Rest>(rest)...);
} else {
// Let's handwave this for the time being
}
};
}
It is possible to translate this hypothetical code into actual C++11 code if we manually 'unroll' the generic lambda into a polymorphic functor:
template<typename F, typename Pointer>
struct wrap_type {
F f;
Pointer pointer;
template<typename... Rest>
auto operator()(Rest&&... rest)
-> decltype( f(*pointer.lock(), std::forward<Rest>(rest)...) )
{
if(auto p = lock()) {
return f(*p, std::forward<Rest>(rest)...);
} else {
// Handle
}
}
};
template<typename F, typename Pointer>
wrap_type<typename std::decay<F>::type, typename std::decay<Pointer>::type>
wrap(F&& f, Pointer&& pointer)
{ return { std::forward<F>(f), std::forward<Pointer>(pointer) }; }
There are two straightforward options for handling the case where the pointer has expired: either propagate an exception, or return an out-of-band value. In the latter case the return type would become e.g. optional<decltype( f(*pointer.lock(), std::forward<Rest>(rest)...) )> and // Handle would become return {};.
Example code to see everything in action.
[ Exercise for the ambitious: improve the code so that it's possible to use auto g = wrap(f, w, 4); auto r = g();. Then, if it's not already the case, improve it further so that auto g = wrap(f, w1, 4, w5); is also possible and 'does the right thing'. ]
I want to move and call a boost::packaged_task inside a lambda.
However, I can't figure out an elegant solution.
e.g. This won't compile.
template<typename Func>
auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept
{
typedef boost::packaged_task<decltype(func())> task_type;
auto task = task_type(std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push([=]
{
try{task();}
catch(boost::task_already_started&){}
});
return std::move(future);
}
int _tmain(int argc, _TCHAR* argv[])
{
executor ex;
ex.begin_invoke([]{std::cout << "Hello world!";});
//error C3848: expression having type 'const boost::packaged_task<R>' would lose some const-volatile qualifiers in order to call 'void boost::packaged_task<R>::operator ()(void)'
// with
// [
// R=void
// ]
return 0;
}
My rather ugly solution:
struct task_adaptor_t
{
// copy-constructor acts as move constructor
task_adaptor_t(const task_adaptor_t& other) : task(std::move(other.task)){}
task_adaptor_t(task_type&& task) : task(std::move(task)){}
void operator()() const { task(); }
mutable task_type task;
} task_adaptor(std::move(task));
execution_queue_.try_push([=]
{
try{task_adaptor();}
catch(boost::task_already_started&){}
});
What is the "proper" way to move a packaged_task into a lambda which calls it?
With a proper implementation of std::bind (or something equivalent with respect to move-enabled types) you should be able to combine bind and a C++0x lambda like this:
task_type task (std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push(std::bind([](task_type const& task)
{
try{task();}
catch(boost::task_already_started&){}
},std::move(task)));
return future;
btw: You don't need a std::move around future because future is a local object. As such, it's already subject to potential copy elision and if the compiler is not able to do that elision it has to move construct the return value from 'future'. The explicit use of std::move in this case may actually inhibit a copy/move elision.
There's a similar question up that I posted about moving into lambdas. C++0x doesn't have any move capture syntax. The only solution I could come up with was some kind of proxy function object.
template<typename T, typename F> class move_capture_proxy {
T t;
F f;
public:
move_capture_proxy(T&& a, F&& b)
: t(std::move(a)), f(std::move(b)) {}
auto operator()() -> decltype(f(std::move(b)) {
return f(std::move(b));
}
};
template<typename T, typename F> move_capture_proxy<T, F> make_move_proxy(T&& t, F&& f) {
return move_capture_proxy<T, F>(std::move(t), std::move(f));
}
execution_queue.try_push(make_move_proxy(std::move(task), [](decltype(task)&& ref) {
auto task = std::move(ref);
// use task
});
Note that I haven't actually tried this code, and it would become a lot nicer with variadic templates, but MSVC10 doesn't have them so I don't really know about them.