#ifndef STD_UTILITY_H
#define STD_UTILITY_H

#include <type_traits>

namespace std 
{
	template< class T >
	constexpr remove_reference_t<T>&& move(T&& t) noexcept {
		return static_cast<typename std::remove_reference<T>::type&&>(t);
	}

	template <typename T>
	inline constexpr enable_if_t<is_move_constructible_v<T> && is_move_assignable_v<T>>
		swap(T& t1, T& t2) noexcept(is_nothrow_move_constructible_v<T>&&
									is_nothrow_move_assignable_v<T>)
	{
		T temp = std::move(t1);
		t1 = std::move(t2);
		t2 = std::move(temp);
	}

	template <class T>
	inline constexpr T&& forward(typename remove_reference<T>::type& t) noexcept 
	{
		return static_cast<T&&>(t);
	}

	template <class T>
	inline constexpr T&& forward(typename remove_reference<T>::type&& t) noexcept 
	{
		static_assert(!is_lvalue_reference<T>::value, "cannot forward an rvalue as an lvalue");
		return static_cast<T&&>(t);
	}

	struct in_place_t 
	{
		explicit in_place_t() = default;
	};

	inline constexpr in_place_t in_place{};
}
#endif