// -*- c++ -*- // C++11 20.4 #pragma once #include <cstddef> #include <utility> namespace std { // // tuple // template <class... Types> class tuple; template <class T0, class... TN> class tuple<T0, TN...> { T0 car_; tuple<TN...> cdr_; template<size_t, typename...> friend struct __get_impl; public: constexpr tuple() : car_(), cdr_() { } explicit tuple(const T0& car, const TN&... cdr) : car_(car), cdr_(tuple<TN...>(cdr...)) { } template<class UType0, class... UTypes> explicit tuple(UType0 &&car, UTypes&&... cdr) : car_(std::forward<UType0>(car)), cdr_(tuple<TN...>(std::forward<UTypes>(cdr)...)) { } tuple(const tuple&) = default; tuple(tuple&&) = default; tuple& operator=(const tuple&) = default; tuple& operator=(tuple&&) = default; void swap(tuple& rhs) { swap(car_, rhs.car_); swap(cdr_, rhs.cdr_); } }; template <> class tuple<> { public: constexpr tuple() { } void swap(tuple& rhs) { } }; // // tuple_element // template <size_t I, class... Types> class tuple_element; template <class T0, class... TN> class tuple_element<0, tuple<T0, TN...> > { public: typedef T0 type; }; template <size_t I, class T0, class... TN> class tuple_element<I, tuple<T0, TN...> > : public tuple_element<I - 1, tuple<TN...> > { }; // // get // template <size_t I, class... Types> struct __get_impl; template <class T0, class... TN> struct __get_impl<0, T0, TN...> { static T0 &get(tuple<T0, TN...>& t) noexcept { return t.car_; } }; template <size_t I, class T0, class... TN> struct __get_impl<I, T0, TN...> { static typename tuple_element<I, tuple<T0, TN...> >::type& get(tuple<T0, TN...>& t) noexcept { return __get_impl<I - 1, TN...>::get(t.cdr_); } }; template <size_t I, class... Types> typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>& t) noexcept { return __get_impl<I, Types...>::get(t); } template <size_t I, class... Types> typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...>&& t) noexcept { return std::forward<typename tuple_element<I, tuple<Types...> > ::type&&>(get<I>(t)); } }