123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- // A very small replacement for boost::tuple
- // (c) Alexander Gessler, 2008
- #ifndef BOOST_TUPLE_INCLUDED
- #define BOOST_TUPLE_INCLUDED
- namespace boost {
- namespace detail {
- // Represents an empty tuple slot (up to 5 supported)
- struct nulltype {};
- // For readable error messages
- struct tuple_component_idx_out_of_bounds;
- // To share some code for the const/nonconst versions of the getters
- template <bool b, typename T>
- struct ConstIf {
- typedef T t;
- };
- template <typename T>
- struct ConstIf<true,T> {
- typedef const T t;
- };
- template <typename, unsigned, typename, bool, unsigned>
- struct value_getter;
- template <typename T, unsigned NIDX, typename TNEXT >
- struct list_elem_base {
- // Store template parameters
- typedef TNEXT next_type;
- typedef T type;
- static const unsigned nidx = NIDX;
- };
- // Represents an element in the tuple component list
- template <typename T, unsigned NIDX, typename TNEXT >
- struct list_elem : list_elem_base<T,NIDX,TNEXT>{
- // Real members
- T me;
- TNEXT next;
- // Get the value of a specific tuple element
- template <unsigned N>
- T& get () {
- value_getter <T,NIDX,TNEXT,false,N> s;
- return s(*this);
- }
- // Get the value of a specific tuple element
- template <unsigned N>
- const T& get () const {
- value_getter <T,NIDX,TNEXT,true,N> s;
- return s(*this);
- }
- // Assign a value to the tuple element
- template <typename T2, typename TNEXT2> /* requires convertible(T2,T) */
- list_elem& operator = (const list_elem<T2,NIDX,TNEXT2>& other) {
- me = (T)other.me;
- next = other.next;
- return *this;
- }
- // Recursively compare two elements
- bool operator == (const list_elem& s) const {
- return (me == s.me && next == s.next);
- }
- };
- // Represents a non-used tuple element - the very last element processed
- template <typename TNEXT, unsigned NIDX >
- struct list_elem<nulltype,NIDX,TNEXT> : list_elem_base<nulltype,NIDX,TNEXT> {
- template <unsigned N, bool IS_CONST = true> struct value_getter {
- /* just dummy members to produce readable error messages */
- tuple_component_idx_out_of_bounds operator () (typename ConstIf<IS_CONST,list_elem>::t& me);
- };
- template <unsigned N> struct type_getter {
- /* just dummy members to produce readable error messages */
- typedef tuple_component_idx_out_of_bounds type;
- };
- // dummy
- list_elem& operator = (const list_elem& other) {
- return *this;
- }
- // dummy
- bool operator == (const list_elem& other) {
- return true;
- }
- };
- // Represents the absolute end of the list
- typedef list_elem<nulltype,0,int> list_end;
- // Helper obtain to query the value of a tuple element
- // NOTE: Could be a nested class, but afaik it's non-standard and at least
- // MSVC isn't able to evaluate the partial specialization correctly.
- template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST, unsigned N>
- struct value_getter {
- // calling list_elem
- typedef list_elem<T,NIDX,TNEXT> outer_elem;
- // typedef for the getter for next element
- typedef value_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,
- IS_CONST, N> next_value_getter;
- typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
- next_value_getter s;
- return s(me.next);
- }
- };
- template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST>
- struct value_getter <T,NIDX,TNEXT,IS_CONST,NIDX> {
- typedef list_elem<T,NIDX,TNEXT> outer_elem;
- typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
- return me.me;
- }
- };
- // Helper to obtain the type of a tuple element
- template <typename T, unsigned NIDX, typename TNEXT, unsigned N /*= 0*/>
- struct type_getter {
- typedef type_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,N> next_elem_getter;
- typedef typename next_elem_getter::type type;
- };
- template <typename T, unsigned NIDX, typename TNEXT >
- struct type_getter <T,NIDX,TNEXT,NIDX> {
- typedef T type;
- };
- };
- // A very minimal implementation for up to 5 elements
- template <typename T0 = detail::nulltype,
- typename T1 = detail::nulltype,
- typename T2 = detail::nulltype,
- typename T3 = detail::nulltype,
- typename T4 = detail::nulltype>
- class tuple {
- friend class tuple;
- private:
- typedef detail::list_elem<T0,0,
- detail::list_elem<T1,1,
- detail::list_elem<T2,2,
- detail::list_elem<T3,3,
- detail::list_elem<T4,4,
- detail::list_end > > > > > very_long;
- very_long m;
- public:
- // Get a specific tuple element
- template <unsigned N>
- typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () {
- return m.get<N>();
- }
- // ... and the const version
- template <unsigned N>
- typename const detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
- return m.get<N>();
- }
- // assignment operator
- tuple& operator= (const tuple& other) {
- m = other.m;
- return *this;
- }
- // comparison operators
- bool operator== (const tuple& other) const {
- return m == other.m;
- }
- // ... and the other way round
- bool operator!= (const tuple& other) const {
- return !(m == other.m);
- }
- // cast to another tuple - all single elements must be convertible
- template < typename T0, typename T1,typename T2,
- typename T3, typename T4>
- operator tuple <T0,T1,T2,T3,T4> () {
- tuple <T0,T1,T2,T3,T4> s;
- s.m = m;
- return s;
- }
- };
- // Another way to access an element ...
- template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
- inline typename tuple<T0,T1,T2,T3,T4>::very_long::type_getter<N>::type& get (
- tuple<T0,T1,T2,T3,T4>& m) {
- return m.get<N>();
- }
- // ... and the const version
- template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
- inline const typename tuple<T0,T1,T2,T3,T4>::very_long::type_getter<N>::type& get (
- const tuple<T0,T1,T2,T3,T4>& m) {
- return m.get<N>();
- }
- // Constructs a tuple with 5 elements
- template <typename T0,typename T1,typename T2,typename T3,typename T4>
- inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0,
- const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
-
- tuple <T0,T1,T2,T3,T4> t;
- t.get<0>() = t0;
- t.get<1>() = t1;
- t.get<2>() = t2;
- t.get<3>() = t3;
- t.get<4>() = t4;
- return t;
- }
- // Constructs a tuple with 4 elements
- template <typename T0,typename T1,typename T2,typename T3>
- inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
- const T1& t1,const T2& t2,const T3& t3) {
- tuple <T0,T1,T2,T3> t;
- t.get<0>() = t0;
- t.get<1>() = t1;
- t.get<2>() = t2;
- t.get<3>() = t3;
- return t;
- }
- // Constructs a tuple with 3 elements
- template <typename T0,typename T1,typename T2>
- inline tuple <T0,T1,T2> make_tuple (const T0& t0,
- const T1& t1,const T2& t2) {
- tuple <T0,T1,T2> t;
- t.get<0>() = t0;
- t.get<1>() = t1;
- t.get<2>() = t2;
- return t;
- }
- // Constructs a tuple with 2 elements (fucking idiot, use std::pair instead!)
- template <typename T0,typename T1>
- inline tuple <T0,T1> make_tuple (const T0& t0,
- const T1& t1) {
- tuple <T0,T1> t;
- t.get<0>() = t0;
- t.get<1>() = t1;
- return t;
- }
- // Constructs a tuple with 1 elements (no comment ...)
- template <typename T0>
- inline tuple <T0> make_tuple (const T0& t0) {
- tuple <T0> t;
- t.get<0>() = t0;
- return t;
- }
- // Constructs a tuple with 0 elements (ehm? Try http://www.promillerechner.net)
- inline tuple <> make_tuple () {
- tuple <> t;
- return t;
- }
- };
- #endif
|