//======================================================================= // Copyright Baptiste Wicht 2013-2016. // Distributed under the terms of the MIT License. // (See accompanying file LICENSE or copy at // http://www.opensource.org/licenses/MIT) //======================================================================= #ifndef TUPLE_H #define TUPLE_H #include #include #include // std::forward / std::move #include #include namespace std { template struct tuple; template struct tuple_element; template struct tuple_element> { using type = nth_type_t; }; template using tuple_element_t = typename tuple_element::type; template const tuple_element_t& get(const tuple& v) noexcept; template tuple_element_t& get(tuple& v) noexcept ; template tuple_element_t&& get(tuple&& v) noexcept ; template struct tuple_value { T value; constexpr tuple_value(){} tuple_value(const T& value) : value(value) { //Nothing else to init } template tuple_value(U&& value) : value(std::forward(value)) { //Nothing else to init } tuple_value( const tuple_value& ) = default; tuple_value( tuple_value&& ) = default; template tuple_value& operator=(U&& value){ this->value = std::forward(value); return *this; } T& get() noexcept { return value; } const T& get() const noexcept { return value; } }; template struct tuple_value> : private T { constexpr tuple_value(){} tuple_value(const T& value) : T(value) { //Nothing else to init } template tuple_value(U&& value) : T(std::forward(value)) { //Nothing else to init } tuple_value( const tuple_value& ) = default; tuple_value( tuple_value&& ) = default; template tuple_value& operator=(U&& value){ static_cast(*this) = std::forward(value); return *this; } T& get() noexcept { return static_cast(*this); } const T& get() const noexcept { return static_cast(*this); } }; using swallow = bool[]; template struct tuple_base; template struct tuple_base, T...> : tuple_value... { constexpr tuple_base() = default; template> constexpr explicit tuple_base(U&&... values) : tuple_value(std::forward(values))... { //Nothing else to init } template constexpr explicit tuple_base(const tuple& values) : tuple_value(get(values))... { //Nothing else to init } template constexpr explicit tuple_base(tuple&& values) : tuple_value(std::forward(get(values)))... { //Nothing else to init } tuple_base( const tuple_base& ) = default; tuple_base( tuple_base&& ) = default; tuple_base& operator=(const tuple_base& v) { (void)swallow{(tuple_value::operator=(static_cast&>(v).get()), true)...}; return *this; } tuple_base& operator=(tuple_base&& v) { (void)swallow{(tuple_value::operator=(std::forward(static_cast&>(v).get())), true)...}; return *this; } template tuple_base& operator=(const tuple& v) { (void)swallow{(tuple_value::operator=(get(v)), true)...}; return *this; } template tuple_base& operator=(tuple&& v) { (void)swallow{(tuple_value::operator=(get(std::move(v))), true)...}; return *this; } }; template struct tuple { using base_t = tuple_base, T...>; base_t base; constexpr tuple() : base(){ //Nothing else to init } constexpr tuple(const T&... values) : base(values...) { //Nothing else to init } template> constexpr tuple(U&&... values) : base(std::forward(values)...) { //Nothing else to init } tuple( const tuple& ) = default; tuple( tuple&& ) = default; template constexpr tuple(const tuple& v) : base(v) { //Nothing else to init } template constexpr tuple(tuple&& v) : base(std::move(v)) { //Nothing else to init } template tuple& operator=(TT&& value){ base = std::forward(value); return *this; } }; template struct tuple_size; template struct tuple_size> { static constexpr const size_t value = sizeof...(T); }; template const nth_type_t& get(const tuple& v) noexcept { return static_cast>&>(v.base).get(); } template nth_type_t& get(tuple& v) noexcept { return static_cast>&>(v.base).get(); } template nth_type_t&& get(tuple&& v) noexcept { return static_cast&&>(static_cast>&&>(v.base).get()); } template inline tuple make_tuple(E&&... args){ return tuple(std::forward(args)...); } template< class... Types > constexpr tuple tie( Types&... args ){ return tuple(args...); } } //end of namespace std #endif