1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
12 #define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24 #include <boost/move/utility_core.hpp>
25 
26 #include <boost/container/detail/type_traits.hpp>
27 #include <cstddef>   //std::size_t
28 
29 namespace boost {
30 namespace container {
31 namespace container_detail {
32 
33 template<typename... Values>
34 class tuple;
35 
36 template<> class tuple<>
37 {};
38 
39 template<typename Head, typename... Tail>
40 class tuple<Head, Tail...>
41    : private tuple<Tail...>
42 {
43    typedef tuple<Tail...> inherited;
44 
45    public:
tuple()46    tuple()
47       : inherited(), m_head()
48    {}
49 
50    template<class U, class ...Args>
tuple(U && u,Args &&...args)51    tuple(U &&u, Args && ...args)
52       : inherited(::boost::forward<Args>(args)...), m_head(::boost::forward<U>(u))
53    {}
54 
55    // Construct tuple from another tuple.
56    template<typename... VValues>
tuple(const tuple<VValues...> & other)57    tuple(const tuple<VValues...>& other)
58       : inherited(other.tail()), m_head(other.head())
59    {}
60 
61    template<typename... VValues>
operator =(const tuple<VValues...> & other)62    tuple& operator=(const tuple<VValues...>& other)
63    {
64       m_head = other.head();
65       tail() = other.tail();
66       return this;
67    }
68 
head()69    typename add_reference<Head>::type head()             {  return m_head; }
head() const70    typename add_reference<const Head>::type head() const {  return m_head; }
71 
tail()72    inherited& tail()             { return *this; }
tail() const73    const inherited& tail() const { return *this; }
74 
75    protected:
76    Head m_head;
77 };
78 
79 
80 template<typename... Values>
forward_as_tuple(Values &&...values)81 tuple<Values&&...> forward_as_tuple(Values&&... values)
82 { return tuple<Values&&...>(::boost::forward<Values>(values)...); }
83 
84 template<int I, typename Tuple>
85 struct tuple_element;
86 
87 template<int I, typename Head, typename... Tail>
88 struct tuple_element<I, tuple<Head, Tail...> >
89 {
90    typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
91 };
92 
93 template<typename Head, typename... Tail>
94 struct tuple_element<0, tuple<Head, Tail...> >
95 {
96    typedef Head type;
97 };
98 
99 template<int I, typename Tuple>
100 class get_impl;
101 
102 template<int I, typename Head, typename... Values>
103 class get_impl<I, tuple<Head, Values...> >
104 {
105    typedef typename tuple_element<I-1, tuple<Values...> >::type   Element;
106    typedef get_impl<I-1, tuple<Values...> >                       Next;
107 
108    public:
109    typedef typename add_reference<Element>::type                  type;
110    typedef typename add_const_reference<Element>::type            const_type;
get(tuple<Head,Values...> & t)111    static type get(tuple<Head, Values...>& t)              { return Next::get(t.tail()); }
get(const tuple<Head,Values...> & t)112    static const_type get(const tuple<Head, Values...>& t)  { return Next::get(t.tail()); }
113 };
114 
115 template<typename Head, typename... Values>
116 class get_impl<0, tuple<Head, Values...> >
117 {
118    public:
119    typedef typename add_reference<Head>::type         type;
120    typedef typename add_const_reference<Head>::type   const_type;
get(tuple<Head,Values...> & t)121    static type       get(tuple<Head, Values...>& t)      { return t.head(); }
get(const tuple<Head,Values...> & t)122    static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
123 };
124 
125 template<int I, typename... Values>
get(tuple<Values...> & t)126 typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
127 {  return get_impl<I, tuple<Values...> >::get(t);  }
128 
129 template<int I, typename... Values>
get(const tuple<Values...> & t)130 typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
131 {  return get_impl<I, tuple<Values...> >::get(t);  }
132 
133 ////////////////////////////////////////////////////
134 // Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
135 // be used to "unpack" into comma-separated values
136 // in a function call.
137 ////////////////////////////////////////////////////
138 
139 template<std::size_t...> struct index_tuple{ typedef index_tuple type; };
140 
141 template<class S1, class S2> struct concat_index_tuple;
142 
143 template<std::size_t... I1, std::size_t... I2>
144 struct concat_index_tuple<index_tuple<I1...>, index_tuple<I2...>>
145   : index_tuple<I1..., (sizeof...(I1)+I2)...>{};
146 
147 template<std::size_t N> struct build_number_seq;
148 
149 template<std::size_t N>
150 struct build_number_seq
151    : concat_index_tuple<typename build_number_seq<N/2>::type
152                        ,typename build_number_seq<N - N/2 >::type
153    >::type
154 {};
155 
156 template<> struct build_number_seq<0> : index_tuple<>{};
157 template<> struct build_number_seq<1> : index_tuple<0>{};
158 
159 }}}   //namespace boost { namespace container { namespace container_detail {
160 
161 #include <boost/container/detail/config_end.hpp>
162 
163 #endif   //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
164