nuclear@0: // A very small replacement for boost::tuple nuclear@0: // (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] nuclear@0: nuclear@0: #ifndef BOOST_TUPLE_INCLUDED nuclear@0: #define BOOST_TUPLE_INCLUDED nuclear@0: nuclear@0: namespace boost { nuclear@0: namespace detail { nuclear@0: nuclear@0: // Represents an empty tuple slot (up to 5 supported) nuclear@0: struct nulltype {}; nuclear@0: nuclear@0: // For readable error messages nuclear@0: struct tuple_component_idx_out_of_bounds; nuclear@0: nuclear@0: // To share some code for the const/nonconst versions of the getters nuclear@0: template nuclear@0: struct ConstIf { nuclear@0: typedef T t; nuclear@0: }; nuclear@0: nuclear@0: template nuclear@0: struct ConstIf { nuclear@0: typedef const T t; nuclear@0: }; nuclear@0: nuclear@0: // Predeclare some stuff nuclear@0: template struct value_getter; nuclear@0: nuclear@0: // Helper to obtain the type of a tuple element nuclear@0: template nuclear@0: struct type_getter { nuclear@0: typedef type_getter next_elem_getter; nuclear@0: typedef typename next_elem_getter::type type; nuclear@0: }; nuclear@0: nuclear@0: template nuclear@0: struct type_getter { nuclear@0: typedef T type; nuclear@0: }; nuclear@0: nuclear@0: // Base class for all explicit specializations of list_elem nuclear@0: template nuclear@0: struct list_elem_base { nuclear@0: nuclear@0: // Store template parameters nuclear@0: typedef TNEXT next_type; nuclear@0: typedef T type; nuclear@0: nuclear@0: static const unsigned nidx = NIDX; nuclear@0: }; nuclear@0: nuclear@0: // Represents an element in the tuple component list nuclear@0: template nuclear@0: struct list_elem : list_elem_base{ nuclear@0: nuclear@0: // Real members nuclear@0: T me; nuclear@0: TNEXT next; nuclear@0: nuclear@0: // Get the value of a specific tuple element nuclear@0: template nuclear@0: typename type_getter::type& get () { nuclear@0: value_getter s; nuclear@0: return s(*this); nuclear@0: } nuclear@0: nuclear@0: // Get the value of a specific tuple element nuclear@0: template nuclear@0: const typename type_getter::type& get () const { nuclear@0: value_getter s; nuclear@0: return s(*this); nuclear@0: } nuclear@0: nuclear@0: // Explicit cast nuclear@0: template nuclear@0: operator list_elem () const { nuclear@0: list_elem ret; nuclear@0: ret.me = (T2)me; nuclear@0: ret.next = next; nuclear@0: return ret; nuclear@0: } nuclear@0: nuclear@0: // Recursively compare two elements (last element returns always true) nuclear@0: bool operator == (const list_elem& s) const { nuclear@0: return (me == s.me && next == s.next); nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: // Represents a non-used tuple element - the very last element processed nuclear@0: template nuclear@0: struct list_elem : list_elem_base { nuclear@0: template struct value_getter { nuclear@0: /* just dummy members to produce readable error messages */ nuclear@0: tuple_component_idx_out_of_bounds operator () (typename ConstIf::t& me); nuclear@0: }; nuclear@0: template struct type_getter { nuclear@0: /* just dummy members to produce readable error messages */ nuclear@0: typedef tuple_component_idx_out_of_bounds type; nuclear@0: }; nuclear@0: nuclear@0: // dummy nuclear@0: list_elem& operator = (const list_elem& other) { nuclear@0: return *this; nuclear@0: } nuclear@0: nuclear@0: // dummy nuclear@0: bool operator == (const list_elem& other) { nuclear@0: return true; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: // Represents the absolute end of the list nuclear@0: typedef list_elem list_end; nuclear@0: nuclear@0: // Helper obtain to query the value of a tuple element nuclear@0: // NOTE: This can't be a nested class as the compiler won't accept a full or nuclear@0: // partial specialization of a nested class of a non-specialized template nuclear@0: template nuclear@0: struct value_getter { nuclear@0: nuclear@0: // calling list_elem nuclear@0: typedef list_elem outer_elem; nuclear@0: nuclear@0: // typedef for the getter for next element nuclear@0: typedef value_getter next_value_getter; nuclear@0: nuclear@0: typename ConstIf::type>::t& nuclear@0: operator () (typename ConstIf::t& me) { nuclear@0: nuclear@0: next_value_getter s; nuclear@0: return s(me.next); nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: template nuclear@0: struct value_getter { nuclear@0: typedef list_elem outer_elem; nuclear@0: nuclear@0: typename ConstIf::t& operator () (typename ConstIf::t& me) { nuclear@0: return me.me; nuclear@0: } nuclear@0: }; nuclear@0: }; nuclear@0: nuclear@0: // A very minimal implementation for up to 5 elements nuclear@0: template nuclear@0: class tuple { nuclear@0: nuclear@0: template nuclear@0: friend class tuple; nuclear@0: nuclear@0: private: nuclear@0: nuclear@0: typedef detail::list_elem > > > > very_long; nuclear@0: nuclear@0: very_long m; nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: // Get a specific tuple element nuclear@0: template nuclear@0: typename detail::type_getter::type& get () { nuclear@0: return m.template get(); nuclear@0: } nuclear@0: nuclear@0: // ... and the const version nuclear@0: template nuclear@0: const typename detail::type_getter::type& get () const { nuclear@0: return m.template get(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // comparison operators nuclear@0: bool operator== (const tuple& other) const { nuclear@0: return m == other.m; nuclear@0: } nuclear@0: nuclear@0: // ... and the other way round nuclear@0: bool operator!= (const tuple& other) const { nuclear@0: return !(m == other.m); nuclear@0: } nuclear@0: nuclear@0: // cast to another tuple - all single elements must be convertible nuclear@0: template nuclear@0: operator tuple () const { nuclear@0: tuple s; nuclear@0: s.m = (typename tuple ::very_long)m; nuclear@0: return s; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: // Another way to access an element ... nuclear@0: template nuclear@0: inline typename tuple::very_long::template type_getter::type& get ( nuclear@0: tuple& m) { nuclear@0: return m.template get(); nuclear@0: } nuclear@0: nuclear@0: // ... and the const version nuclear@0: template nuclear@0: inline const typename tuple::very_long::template type_getter::type& get ( nuclear@0: const tuple& m) { nuclear@0: return m.template get(); nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 5 elements nuclear@0: template nuclear@0: inline tuple make_tuple (const T0& t0, nuclear@0: const T1& t1,const T2& t2,const T3& t3,const T4& t4) { nuclear@0: nuclear@0: tuple t; nuclear@0: t.template get<0>() = t0; nuclear@0: t.template get<1>() = t1; nuclear@0: t.template get<2>() = t2; nuclear@0: t.template get<3>() = t3; nuclear@0: t.template get<4>() = t4; nuclear@0: return t; nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 4 elements nuclear@0: template nuclear@0: inline tuple make_tuple (const T0& t0, nuclear@0: const T1& t1,const T2& t2,const T3& t3) { nuclear@0: tuple t; nuclear@0: t.template get<0>() = t0; nuclear@0: t.template get<1>() = t1; nuclear@0: t.template get<2>() = t2; nuclear@0: t.template get<3>() = t3; nuclear@0: return t; nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 3 elements nuclear@0: template nuclear@0: inline tuple make_tuple (const T0& t0, nuclear@0: const T1& t1,const T2& t2) { nuclear@0: tuple t; nuclear@0: t.template get<0>() = t0; nuclear@0: t.template get<1>() = t1; nuclear@0: t.template get<2>() = t2; nuclear@0: return t; nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 2 elements nuclear@0: template nuclear@0: inline tuple make_tuple (const T0& t0, nuclear@0: const T1& t1) { nuclear@0: tuple t; nuclear@0: t.template get<0>() = t0; nuclear@0: t.template get<1>() = t1; nuclear@0: return t; nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 1 elements (well ...) nuclear@0: template nuclear@0: inline tuple make_tuple (const T0& t0) { nuclear@0: tuple t; nuclear@0: t.template get<0>() = t0; nuclear@0: return t; nuclear@0: } nuclear@0: nuclear@0: // Constructs a tuple with 0 elements (well ...) nuclear@0: inline tuple <> make_tuple () { nuclear@0: tuple <> t; nuclear@0: return t; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: #endif // !! BOOST_TUPLE_INCLUDED