- #include <iostream> 
- #include <memory> 
-   
- struct copyableMovable  
- { 
-     copyableMovable() { std::cout << "\tcopyableMovable()\t"; } 
-     copyableMovable(const copyableMovable&) noexcept { std::cout << "\tcopyableMovable(const copyableMovable&)\n"; } 
-     copyableMovable(copyableMovable&&) noexcept { std::cout << "\tcopyableMovable(copyableMovable&&)\n"; } 
- }; 
-   
- struct onlyMovable  
- { 
-     onlyMovable() { std::cout << "\tonlyMovable()\t"; } 
-     onlyMovable(onlyMovable&&) { std::cout << "\tonlyMovable(onlyMovable&&)\n"; } 
-     onlyMovable(const onlyMovable&) = delete;  
- }; 
-   
- struct byValue  
- { 
-     byValue(copyableMovable) { std::cout << "byValue(copyableMovable)\n"; } 
-     byValue(onlyMovable) { std::cout << "byValue(onlyMovable)\n"; } 
- }; 
- struct byReference  
- { 
-     byReference(copyableMovable&) { std::cout << "byReference(copyableMovable&)\n"; } 
-     byReference(onlyMovable&) { std::cout << "byReference(onlyMovable&)\n"; } 
- }; 
- struct byConstReference  
- { 
-     byConstReference(const copyableMovable&) { std::cout << "byConstReference(const copyableMovable&)\n"; } 
-     byConstReference(const onlyMovable&) { std::cout << "byConstReference(const onlyMovable&)\n"; } 
- }; 
- struct byRvalueReference  
- { 
-     byRvalueReference(copyableMovable&&) { std::cout << "byRvalueReference(copyableMovable&&)\n"; } 
-     byRvalueReference(onlyMovable&&) { std::cout << "byRvalueReference(onlyMovable&&)\n"; } 
- }; 
-   
-   
- template <typename T, typename Arg> 
- std::unique_ptr<T> without_forward(Arg arg)                                        
- { return std::unique_ptr<T>(new T(arg)); } 
-   
- template <typename T, typename Arg> 
- std::unique_ptr<T> with_forward(Arg arg)                                        
- { return std::unique_ptr<T>(new T(std::forward<Arg>(arg))); } 
-   
-   
- int main()  
- { 
-    std::cout << "\tIDEA\nPassing lvalues and rvalues to function that return unique_ptr for them.\nWe have two kinds of objects:\n"; 
-    copyableMovable cm{};	std::cout << " - can be copied and moved along i. e. not restricted at all.\n"; 
-    onlyMovable om{};		std::cout << " - can be moved but cannot be copied, i. e. unique_ptr or streams etc.\n"; 
-   
-    std::cout << "\n\n\n\tWITHOUT FORWARD\n"; 
-   
-    std::cout << "BY VALUE\n"; 
-    std::cout << "Lvalue - copyable:\n";	auto val_copy_l = without_forward<byValue>(cm); 
-    std::cout << "\nLvalue - moveable:\n";	//auto val_move_l = without_forward<byValue>(om); 
-    std::cout << "Impossible, needs copy constructor.\n"; 
-    std::cout << "\nRvalue - copyable:\n";	auto val_copy_r = without_forward<byValue>(copyableMovable{}); 
-    std::cout << "\nRvalue - moveable:\n";	//auto val_move_r = without_forward<byValue>(onlyMovable{}); 
-    std::cout << "Impossible, needs copy constructor.\n\n"; 
-   
-    std::cout << "BY REFERENCE\n"; 
-    std::cout << "Lvalue - copyable:\n";	auto ref_copy_l = without_forward<byReference>(cm); 
-    std::cout << "\nLvalue - moveable:\n";	//auto ref_move_l = without_forward<byReference>(om); 
-    std::cout << "Impossible, needs copy constructor\n"; 
-    std::cout << "\nRvalue - copyable:\n";	auto ref_copy_r = without_forward<byReference>(copyableMovable{}); 
-    std::cout << "\nRvalue - moveable:\n";	auto ref_move_r = without_forward<byReference>(onlyMovable{}); 
-   
-    std::cout << "BY CONST REFERENCE\n"; 
-    std::cout << "\nLvalue - copyable:\n";	auto cref_copy_l = without_forward<byConstReference>(cm); 
-    std::cout << "\nLvalue - moveable:\n";	//auto cref_move_l = without_forward<byConstReference>(om); 
-    std::cout << "Impossible, needs copy constructor\n"; 
-    std::cout << "\nRvalue - copyable:\n";	auto cref_copy_r = without_forward<byConstReference>(copyableMovable{}); 
-    std::cout << "\nRvalue - moveable:\n";	auto cref_move_r = without_forward<byConstReference>(onlyMovable{}); 
-   
-    std::cout << "BY RVALUE REFERENCE\n"; 
-    std::cout << "\nLvalue - copyable:\n";	//auto rref_copy_l = without_forward<byRvalueReference>(copyableMovable{}); 
-    std::cout << "Lvalue - moveable:\n";	//auto rref_move_l = without_forward<byRvalueReference>(onlyMovable{}); 
-    std::cout << "Rvalue - copyable:\n";	//auto rref_copy_r = without_forward<byRvalueReference>(copyableMovable{}); 
-    std::cout << "Rvalue - moveable:\n";	//auto rref_move_r = without_forward<byRvalueReference>(onlyMovable{}); 
-    std::cout << "Evarything impossible: they all need an rvalue, but receive an lvalue.\n"; 
-   
-    std::cout << "\nWithout forward - short summary:\nPassing by value is impossible for onlyMovable." 
- 		"\nPassing by lvalue reference is impossible for onlyMovable rvalues." 
- 		"\nPassing by rvalue does not work at all.\n"; 
-   
-   
-    std::cout << "\n\n\n\tWITH FORWARD\n"; 
-   
-    std::cout << "BY VALUE\n"; 
-    std::cout << "Lvalue - copyable:\n";	auto val_copy_lf = with_forward<byValue>(cm); 
-    std::cout << "\nLvalue - moveable:\n";	//auto val_move_lf = with_forward<byValue>(om); 
-    std::cout << "Impossible, needs copy constructor.\n"; 
-    std::cout << "\nRvalue - copyable:\n";	auto val_copy_rf = with_forward<byValue>(copyableMovable{}); 
-    std::cout << "\nRvalue - moveable:\n";	auto val_move_rf = with_forward<byValue>(onlyMovable{}); 
-   
-    std::cout << "\nBY REFERENCE\n"; 
-    std::cout << "Lvalue - copyable:\n";	//auto ref_copy_lf = with_forward<byReference>(cm); 
-    std::cout << "Lvalue - moveable:\n";	//auto ref_move_lf = with_forward<byReference>(om); 
-    std::cout << "Rvalue - copyable:\n";	//auto ref_copy_rf = with_forward<byReference>(copyableMovable{}); 
-    std::cout << "Rvalue - moveable:\n";	//auto ref_move_rf = with_forward<byReference>(onlyMovable{}); 
-    std::cout << "All impossible - lvalue needed, not rvalue.\n"; 
-   
-    std::cout << "\nBY CONST REFERENCE\n"; 
-    std::cout << "\nLvalue - copyable:\n";	auto cref_copy_lf = with_forward<byConstReference>(cm); 
-    std::cout << "\nLvalue - moveable:\n";	//auto cref_move_lf = with_forward<byConstReference>(om); 
-    std::cout << "Impossible, needs copy constructor\n"; 
-    std::cout << "\nRvalue - copyable:\n";	auto cref_copy_rf = with_forward<byConstReference>(copyableMovable{}); 
-    std::cout << "\nRvalue - moveable:\n";	auto cref_move_rf = with_forward<byConstReference>(onlyMovable{}); 
-   
-    std::cout << "\nBY RVALUE REFERENCE\n"; 
-    std::cout << "\nLvalue - copyable:\n";	auto rref_copy_lf = with_forward<byRvalueReference>(copyableMovable{}); 
-    std::cout << "Lvalue - moveable:\n";	auto rref_move_lf = with_forward<byRvalueReference>(onlyMovable{}); 
-    std::cout << "Rvalue - copyable:\n";	auto rref_copy_rf = with_forward<byRvalueReference>(copyableMovable{}); 
-    std::cout << "Rvalue - moveable:\n";	auto rref_move_rf = with_forward<byRvalueReference>(onlyMovable{}); 
-    std::cout << "With forward - short summary:\nPassing by value is impossible for onlyMovable lvalue.\n" 
- 		"Passing by non const lvalue reference does not work at all.\n" 
- 		"Passing by const lvalue reference is impossible for onlyMovable lvalue.\n"; 
-   
-    std::cout << "\n\nSUMMARY\nAfter enabling forward in function rerturning unique_ptr to it's argument:\n" 
- 		" - passing onlyMovable rvalue by value becomes possible\n" 
- 		" - passing lvalue copyableMovable and all rvalues by non const lvalue reference becomes impossible\n" 
- 		" - passing by const lvalue reference does not change\n" 
- 		" - passing by rvalue reference becomes possible for both lvalues and rvalues of both copyableMovable and onlyMovable\n" 
- 		"Experiment overlooks onlyCopyable type.\n"; 
- }