Created
December 1, 2012 18:42
-
-
Save je4d/4183939 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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