Skip to content

Instantly share code, notes, and snippets.

@je4d
Created December 1, 2012 18:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save je4d/4183939 to your computer and use it in GitHub Desktop.
Save je4d/4183939 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <type_traits>
#include <utility>
template<typename T>
struct move_on_copy
{
move_on_copy(T&& aValue) : value(std::move(aValue)) {}
move_on_copy(const move_on_copy& other) : value(std::move(other.value)) {}
mutable T value;
private:
move_on_copy& operator=(move_on_copy&& aValue) = delete; // not needed here
move_on_copy& operator=(const move_on_copy& aValue) = delete; // not needed here
};
#define RVALUE_RESTRICTION 1
#if RVALUE_RESTRICTION == 0
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));
}
/* move-fail.cpp:27:17: error: expected nested-name-specifier before ‘enable_if’
* move-fail.cpp:27:17: error: expected initializer before ‘enable_if’
* move-fail.cpp: In function ‘int main()’:
* move-fail.cpp:67:26: error: ‘make_move_on_copy’ was not declared in this scope
*/
#elif RVALUE_RESTRICTION == 1
template<typename T>
move_on_copy<typename std::remove_reference<T>::type> make_move_on_copy_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<typename std::remove_reference<T>::type> make_move_on_copy(T&& aValue)
{
return make_move_on_copy_internal<T>(std::forward<T>(aValue));
}
/* move-fail.cpp: In instantiation of ‘move_on_copy<typename std::remove_reference< <template-parameter-1-1> >::type> make_move_on_copy(T&&) [with T = Foo&; typename std::remove_reference< <template-parameter-1-1> >::type = Foo]’:
* move-fail.cpp:82:26: required from here
* move-fail.cpp:47:65: error: no matching function for call to ‘make_move_on_copy_internal(Foo&)’
* move-fail.cpp:47:65: note: candidate is:
* move-fail.cpp:39:55: note: template<class T> move_on_copy<typename std::remove_reference< <template-parameter-1-1> >::type> make_move_on_copy_internal(typename std::remove_reference<_Tp>::type&&)
* move-fail.cpp:39:55: note: template argument deduction/substitution failed:
* move-fail.cpp:47:65: note: cannot convert ‘std::forward<Foo&>((* & aValue))’ (type ‘Foo’) to type ‘std::remove_reference<Foo&>::type&& {aka Foo&&}’
*/
#elif RVALUE_RESTRICTION == 2
template<typename T>
move_on_copy<T> make_move_on_copy_internal(T&& aValue)
{
return move_on_copy<T>(std::move(aValue));
}
template<typename T>
move_on_copy<typename std::remove_reference<T>::type> make_move_on_copy(T&& aValue)
{
return make_move_on_copy_internal<typename std::remove_reference<T>::type>(std::forward<T>(aValue));
}
/* move-fail.cpp: In instantiation of ‘move_on_copy<typename std::remove_reference< <template-parameter-1-1> >::type> make_move_on_copy(T&&) [with T = Foo&; typename std::remove_reference< <template-parameter-1-1> >::type = Foo]’:
* move-fail.cpp:76:26: required from here
* move-fail.cpp:50:103: error: no matching function for call to ‘make_move_on_copy_internal(Foo&)’
* move-fail.cpp:50:103: note: candidate is:
* move-fail.cpp:42:17: note: template<class T> move_on_copy<T> make_move_on_copy_internal(T&&)
* move-fail.cpp:42:17: note: template argument deduction/substitution failed:
* move-fail.cpp:50:103: note: cannot convert ‘std::forward<Foo&>((* & aValue))’ (type ‘Foo’) to type ‘Foo&&’
*
*/
#endif
struct Foo
{
Foo() {}
Foo(const Foo&) { std::cout << "copied" << std::endl;}
Foo(Foo&&) { std::cout << "moved" << std::endl;}
};
int main()
{
Foo foo;
make_move_on_copy(foo);
make_move_on_copy(std::move(foo));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment