#include <functional>
#include <iostream>
#include <vector>
//////////////////////////////////////////////////////////////////////////////// MOVE_ON_COPY
template<typename T>
struct move_on_copy
{
move_on_copy(T&& aValue) : value(move(aValue)) {}
move_on_copy(const move_on_copy& other) : value(move(other.value)) {}
T& Value()
{
return value;
}
const T& Value() const
{
return value;
}
private:
mutable T value;
move_on_copy& operator=(move_on_copy&& aValue);
move_on_copy& operator=(const move_on_copy& aValue);
};
template <typename T>
move_on_copy<typename std::remove_reference<T>::type> make_move_on_copy_wrapper_internal(typename std::remove_reference<T>::type&& aValue)
{
return move_on_copy<typename std::remove_reference<T>::type>(std::move(aValue));
}
template <typename T>
move_on_copy<T> make_move_on_copy_wrapper(T&& aValue)
{
return make_move_on_copy_wrapper_internal<T>(std::forward<T>(aValue));
}
//////////////////////////////////////////////////////////////////////////////// MOVE_ON_COPY
template<typename T>
struct mfunction;
template<class ReturnType, typename... ParamType>
struct mfunction<ReturnType(ParamType...)> : public std::function<ReturnType(ParamType...)>
{
typedef std::function<ReturnType(ParamType...)> FnType;
mfunction() : FnType()
{}
template<typename T>
explicit mfunction(T&& fn) : FnType(std::forward<T>(fn))
{}
mfunction(mfunction&& other) : FnType(move(static_cast<FnType&&>(other)))
{}
mfunction& operator=(mfunction&& other)
{
FnType::operator=(move(static_cast<FnType&&>(other)));
return *this;
}
mfunction(const mfunction&) = delete;
mfunction& operator=(const mfunction&) = delete;
};
// examples
using namespace std;
struct ToCapture
{
ToCapture() {}
ToCapture(ToCapture const&) { cout << "copied!" << endl; }
ToCapture(ToCapture&&) { cout << "moved!" << endl; }
};
void myFunction()
{
cout << "myFunction" << endl;
}
mfunction<void()> Create()
{
vector<int> vec {1,2,3};
auto wrap = make_move_on_copy_wrapper(move(vec));
mfunction<void()> f([wrap](){ cout << wrap.Value().size() << endl; });
return f;
}
int use_m_function_as_std_function(function<int(int, int)>& f)
{
return f(10,20);
}
int main()
{
//1) creation
ToCapture toCapt;
// from lambda
mfunction<void(int, string)> mfunction_1 ( [toCapt] (int i, string s) { cout << s << " " << i << endl;} );
mfunction_1(1, "Hello");
// from function pointer
mfunction<void()> m_function_2 (&myFunction);
m_function_2();
// from std::function
std::function<void(int)> stdFunc1 ([toCapt](int) {});
cout << "---stdFunc1 created---" << endl;
mfunction<void(int)> m_function3 (stdFunc1);
stdFunc1(1);
m_function3(1);
//2) noncopyability
// auto mfunction_2 = mfunction_1;
auto mfunction_2 = move(mfunction_1);
//mfunction_2 = [](int,string){};
//m_function_2 = mfunction_1;
//3) using
auto mfunction_3 = Create();
mfunction_3();
mfunction<int(int,int)> mfunction_4([](int a, int b){ return a+b; });
cout << use_m_function_as_std_function(mfunction_4) << endl;
return 0;
}