#include <iostream>
#include <type_traits>
#include <memory>
#include <string>
#include <vector>
using namespace std;
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>
auto make_move_on_copy(T&& aValue) -> typename enable_if<is_rvalue_reference<decltype(aValue)>::value, move_on_copy<T>>::type
{
return move_on_copy<T>(move(aValue));
}
template<typename F>
void invoke(F f)
{
f();
}
// some trials
int main()
{
unique_ptr<int> aPtr(new int(5));
auto aPtrMov = make_move_on_copy(move(aPtr));
unique_ptr<int> aPtr2(new int(5));
auto aPtrMov2 = make_move_on_copy(move(aPtr2));
auto aPtrLam = [aPtrMov]
{
cout << "Ptr value: " << *(aPtrMov.Value()) << endl;
};
auto aPtrMutableLam = [aPtrMov2] () mutable
{
(*aPtrMov2.Value())++;
cout << "Ptr value: " << *(aPtrMov2.Value()) << endl;
};
invoke(aPtrLam);
invoke(aPtrMutableLam);
invoke(aPtrMutableLam);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxtZW1vcnk+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx2ZWN0b3I+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IG1vdmVfb25fY29weSAKewoJbW92ZV9vbl9jb3B5KFQmJiBhVmFsdWUpIDogdmFsdWUobW92ZShhVmFsdWUpKSB7fQoJbW92ZV9vbl9jb3B5KGNvbnN0IG1vdmVfb25fY29weSYgb3RoZXIpIDogdmFsdWUobW92ZShvdGhlci52YWx1ZSkpIHt9CgkKCVQmIFZhbHVlKCkgCgl7CgkJcmV0dXJuIHZhbHVlOwoJfQoJCgljb25zdCBUJiBWYWx1ZSgpIGNvbnN0Cgl7CgkJcmV0dXJuIHZhbHVlOwoJfQoJCnByaXZhdGU6CgltdXRhYmxlIFQgdmFsdWU7Cgltb3ZlX29uX2NvcHkmIG9wZXJhdG9yPShtb3ZlX29uX2NvcHkmJiBhVmFsdWUpOwoJbW92ZV9vbl9jb3B5JiBvcGVyYXRvcj0oY29uc3QgbW92ZV9vbl9jb3B5JiBhVmFsdWUpOwp9OwoKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmF1dG8gbWFrZV9tb3ZlX29uX2NvcHkoVCYmIGFWYWx1ZSkgLT4gdHlwZW5hbWUgZW5hYmxlX2lmPGlzX3J2YWx1ZV9yZWZlcmVuY2U8ZGVjbHR5cGUoYVZhbHVlKT46OnZhbHVlLCBtb3ZlX29uX2NvcHk8VD4+Ojp0eXBlCnsKCXJldHVybiBtb3ZlX29uX2NvcHk8VD4obW92ZShhVmFsdWUpKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgRj4Kdm9pZCBpbnZva2UoRiBmKQp7CiAgICBmKCk7Cn0KCi8vIHNvbWUgdHJpYWxzCmludCBtYWluKCkgCnsKICAgCXVuaXF1ZV9wdHI8aW50PiBhUHRyKG5ldyBpbnQoNSkpOwoJYXV0byBhUHRyTW92ID0gbWFrZV9tb3ZlX29uX2NvcHkobW92ZShhUHRyKSk7Cgl1bmlxdWVfcHRyPGludD4gYVB0cjIobmV3IGludCg1KSk7CglhdXRvIGFQdHJNb3YyID0gbWFrZV9tb3ZlX29uX2NvcHkobW92ZShhUHRyMikpOwoKCWF1dG8gYVB0ckxhbSA9IFthUHRyTW92XSAKCXsKCQljb3V0IDw8ICJQdHIgdmFsdWU6ICIgPDwgKihhUHRyTW92LlZhbHVlKCkpIDw8IGVuZGw7Cgl9OwoKCWF1dG8gYVB0ck11dGFibGVMYW0gPSBbYVB0ck1vdjJdICgpIG11dGFibGUKCXsKCQkoKmFQdHJNb3YyLlZhbHVlKCkpKys7CgkJY291dCA8PCAiUHRyIHZhbHVlOiAiIDw8ICooYVB0ck1vdjIuVmFsdWUoKSkgPDwgZW5kbDsKCX07ICAgCgoJaW52b2tlKGFQdHJMYW0pOwoJaW52b2tlKGFQdHJNdXRhYmxlTGFtKTsKCWludm9rZShhUHRyTXV0YWJsZUxhbSk7CgoKICAgcmV0dXJuIDA7Cn0=