Location>code7788 >text

An Introduction to Right-Valued References Move Semantics Perfect Forward std::move::forward, a peek at template metaprogramming

Popularity:419 ℃/2024-12-12 21:00:19
#include <iostream> #include <utility> // for std::move, std::forward #include <type_traits> // for remove_reference_t, is_lvalue_reference_v // C++14 version of std::move template<typename _Tp> constexpr decltype(auto) move(_Tp&& __t) noexcept { return static_cast<std::remove_reference_t<_Tp>&&>(__t); } // C++14 version of std::forward for lvalues template<typename _Tp> constexpr decltype(auto) forward(std::remove_reference_t<_Tp>& __t) noexcept { return static_cast<_Tp&&>(__t); } // C++14 version of std::forward for rvalues template<typename _Tp> constexpr decltype(auto) forward(std::remove_reference_t<_Tp>&& __t) noexcept { static_assert(!std::is_lvalue_reference_v<_Tp>, "template argument substituting _Tp is an lvalue reference type"); return static_cast<_Tp&&>(__t); } // Test class with move and copy constructors class Widget { public: Widget() { std::cout << "Widget default constructor\n"; } Widget(const Widget&) { std::cout << "Widget copy constructor\n"; } Widget(Widget&&) noexcept { std::cout << "Widget move constructor\n"; } }; // Function to test std::forward template <typename T> void forward_test(T&& arg) { Widget w = std::forward<T>(arg); } int main() { // Test std::move Widget widget1; std::cout << "Using std::move:\n"; Widget widget2 = std::move(widget1); // Should call move constructor // Test std::forward with lvalue std::cout << "\nUsing std::forward with lvalue:\n"; Widget widget3; forward_test(widget3); // Should call copy constructor // Test std::forward with rvalue std::cout << "\nUsing std::forward with rvalue:\n"; forward_test(Widget()); // Should call move constructor return 0; }