Create a gist now

Instantly share code, notes, and snippets.

Capture by Move Lambda - C++11
#include <utility>
#include <iostream>
#include <memory>
#include <type_traits>
#include <functional>
template<class T>
using moved_value = std::reference_wrapper<T>;
template<class T,class F>
struct move_lambda{
T val;
F f_;
move_lambda(T&& v, F f):val(std::move(v)),f_(f){};
move_lambda(move_lambda&& other) = default;
move_lambda& operator=(move_lambda&& other) = default;
template<class... Args>
auto operator()(Args&& ...args) -> decltype(this->f_(moved_value<T>(this->val),std::forward<Args>(args)...))
moved_value<T> mv(val);
return f_(mv,std::forward<Args>(args)...);
move_lambda() = delete;
move_lambda(const move_lambda&) = delete;
move_lambda& operator=(const move_lambda&) = delete;
template<class T,class F>
move_lambda<T,F>create_move_lambda(T&& t, F f){
return move_lambda<T,F>(std::move(t),f);
// Unfortunately, std::function does not seem to support move-only callables
// See § point 7 where it requires F be CopyConstructible
// From draft at
// Here is our movable replacement for std::function
template< class ReturnType, class... ParamTypes>
struct movable_function_base{
virtual ReturnType callFunc(ParamTypes&&... p) = 0;
template<class F, class ReturnType, class... ParamTypes>
struct movable_function_imp:public movable_function_base<ReturnType,ParamTypes...>{
F f_;
virtual ReturnType callFunc(ParamTypes&&... p){
return f_(std::forward<ParamTypes>(p)...);
explicit movable_function_imp(F&& f):f_(std::move(f)){};
movable_function_imp() = delete;
movable_function_imp(const movable_function_imp&) = delete;
movable_function_imp& operator=(const movable_function_imp&) = delete;
template<class FuncType>
struct movable_function{};
template<class ReturnType, class... ParamTypes>
struct movable_function<ReturnType(ParamTypes...)>{
std::unique_ptr<movable_function_base<ReturnType,ParamTypes...>> ptr_;
template<class F>
explicit movable_function(F&& f):ptr_(new movable_function_imp<F,ReturnType,ParamTypes...>(std::move(f))){}
movable_function(movable_function&& other) = default;
movable_function& operator=(movable_function&& other) = default;
template<class... Args>
auto operator()(Args&& ...args) -> ReturnType
return ptr_->callFunc(std::forward<Args>(args)...);
movable_function() = delete;
movable_function(const movable_function&) = delete;
movable_function& operator=(const movable_function&) = delete;
// This is a movable only object
struct TestMove{
TestMove(TestMove&& other):k(other.k){
other.k = -1;
TestMove& operator=(TestMove&& other){
k = other.k;
other.k = -1;
return *this;
int k;
TestMove(const TestMove&) = delete;
TestMove& operator=(const TestMove&) = delete;
movable_function<void()> CreateLambda()
// Pretend our TestMove is a HugeObject that we do not want to copy
typedef TestMove HugeObject;
// Manipulate our "HugeObject"
HugeObject hugeObj;
hugeObj.k = 9;
auto f = create_move_lambda(std::move(hugeObj),[](moved_value<HugeObject> hugeObj){// manipulate huge object
std::cout << hugeObj.get().k << std::endl;
movable_function<void()> toReturn(std::move(f));
return toReturn;
int main(){
// A movable only type, not copyable
TestMove m;
m.k = 5;
// A movable only type, not copyable
TestMove m2;
m2.k = 6;
// Create a lambda that takes 2 parameters and returns int
auto lambda = create_move_lambda(std::move(m),[](moved_value<TestMove> m,int i,int)->int{
std::cout << m.get().k << " " << i << std::endl;return 7;
// Create a lambda that takes 0 parameters and returns void
auto lambda2 = create_move_lambda(std::move(m2),[](moved_value<TestMove> m){
std::cout << m.get().k << std::endl;
std::cout << lambda(1,2) << std::endl;
// Compiler error if you try to copy
//auto lambda4 = lambda;
// Able to move
auto lambda3 = std::move(lambda2);
auto lambda4 = CreateLambda();
// A movable only type, not copyable
TestMove m3;
m3.k = 6;
// You can take a reference instead of a moved_value if you want
auto lambda5 = create_move_lambda(std::move(m3),[](TestMove& m){
std::cout << m.k << std::endl;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment