OSDN Git Service

2008-01-18 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / std / tuple
1 // <tuple> -*- C++ -*-
2
3 // Copyright (C) 2007, 2008 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING.  If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 /** @file include/tuple
31  *  This is a Standard C++ Library header.
32  */
33
34 #ifndef _GLIBCXX_CXX0X_TUPLE
35 #define _GLIBCXX_CXX0X_TUPLE 1
36
37 #pragma GCC system_header
38
39 #ifndef __GXX_EXPERIMENTAL_CXX0X__
40 # include <c++0x_warning.h>
41 #endif
42
43 #include <utility>
44
45 namespace std
46 {
47   // Adds a const reference to a non-reference type.
48   template<typename _Tp>
49     struct __add_c_ref
50     { typedef const _Tp& type; };
51
52   template<typename _Tp>
53     struct __add_c_ref<_Tp&>
54     { typedef _Tp& type; };
55
56   // Adds a reference to a non-reference type.
57   template<typename _Tp>
58     struct __add_ref
59     { typedef _Tp& type; };
60
61   template<typename _Tp>
62     struct __add_ref<_Tp&>
63     { typedef _Tp& type; };
64
65   template<int _Idx, typename _Head, bool _IsEmpty>
66     struct _Head_base;
67
68   template<int _Idx, typename _Head>
69     struct _Head_base<_Idx, _Head, true>
70     : public _Head
71     {
72       _Head_base()
73       : _Head() { }
74
75       _Head_base(typename __add_c_ref<_Head>::type __h)
76       : _Head(__h) { }
77
78       _Head_base(typename std::remove_reference<_Head>::type&& __h)
79       : _Head(std::forward<_Head>(__h)) { }
80
81       _Head&       _M_head()       { return *this; }
82       const _Head& _M_head() const { return *this; }
83     };
84
85   template<int _Idx, typename _Head>
86     struct _Head_base<_Idx, _Head, false>
87     {
88       _Head_base()
89       : _M_head_impl() { }
90
91       _Head_base(typename __add_c_ref<_Head>::type __h)
92       : _M_head_impl(__h) { }
93
94       _Head_base(typename std::remove_reference<_Head>::type&& __h)
95       : _M_head_impl(std::move(__h)) { }
96
97       _Head&       _M_head()       { return _M_head_impl; }
98       const _Head& _M_head() const { return _M_head_impl; }        
99
100       _Head _M_head_impl; 
101     };
102
103   /**
104    * Contains the actual implementation of the @c tuple template, stored
105    * as a recursive inheritance hierarchy from the first element (most
106    * derived class) to the last (least derived class). The @c Idx
107    * parameter gives the 0-based index of the element stored at this
108    * point in the hierarchy; we use it to implement a constant-time
109    * get() operation.
110    */
111   template<int _Idx, typename... _Elements>
112     struct _Tuple_impl; 
113
114   /**
115    * Zero-element tuple implementation. This is the basis case for the 
116    * inheritance recursion.
117    */
118   template<int _Idx>
119     struct _Tuple_impl<_Idx> { };
120
121   /**
122    * Recursive tuple implementation. Here we store the @c Head element
123    * and derive from a @c Tuple_impl containing the remaining elements
124    * (which contains the @c Tail).
125    */
126   template<int _Idx, typename _Head, typename... _Tail>
127     struct _Tuple_impl<_Idx, _Head, _Tail...>
128     : public _Tuple_impl<_Idx + 1, _Tail...>,
129       private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
130     {
131       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
132       typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
133
134       _Head&            _M_head()       { return _Base::_M_head(); }
135       const _Head&      _M_head() const { return _Base::_M_head(); }
136
137       _Inherited&       _M_tail()       { return *this; }
138       const _Inherited& _M_tail() const { return *this; }
139
140       _Tuple_impl()
141       : _Inherited(), _Base() { }
142
143       explicit 
144       _Tuple_impl(typename __add_c_ref<_Head>::type __head,
145                   typename __add_c_ref<_Tail>::type... __tail)
146       : _Inherited(__tail...), _Base(__head) { }
147
148       template<typename _UHead, typename... _UTail> 
149         explicit
150         _Tuple_impl(typename std::remove_reference<_UHead>::type&& __head,
151                     typename std::remove_reference<_UTail>::type&&... __tail)
152         : _Inherited(std::forward<_Inherited>(__tail)...),
153           _Base(std::forward<_Base>(__head)) { }
154
155       _Tuple_impl(const _Tuple_impl& __in)
156       : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
157
158       _Tuple_impl(_Tuple_impl&& __in)
159       : _Inherited(std::forward<_Inherited>(__in._M_tail())),
160         _Base(std::forward<_Base>(__in._M_head())) { }
161
162       template<typename... _UElements>
163         _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
164         : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
165
166       template<typename... _UElements>
167         _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in)
168         : _Inherited(std::forward<_Inherited>(__in._M_tail())),
169           _Base(std::forward<_Base>(__in._M_head())) { }
170
171       _Tuple_impl&
172       operator=(const _Tuple_impl& __in)
173       {
174         _M_head() = __in._M_head();
175         _M_tail() = __in._M_tail();
176         return *this;
177       }
178
179       _Tuple_impl&
180       operator=(_Tuple_impl&& __in)
181       {
182         _M_head() = std::move(__in._M_head());
183         _M_tail() = std::move(__in._M_tail());
184         return *this;
185       }
186
187       template<typename... _UElements>
188         _Tuple_impl&
189         operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
190         {
191           _M_head() = __in._M_head();
192           _M_tail() = __in._M_tail();
193           return *this;
194         }
195
196       template<typename... _UElements>
197         _Tuple_impl&
198         operator=(_Tuple_impl<_Idx, _UElements...>&& __in)
199         {
200           _M_head() = std::move(__in._M_head());
201           _M_tail() = std::move(__in._M_tail());
202           return *this;
203         }
204     };
205
206   template<typename... _Elements> 
207     class tuple : public _Tuple_impl<0, _Elements...>
208     {
209       typedef _Tuple_impl<0, _Elements...> _Inherited;
210
211     public:
212       tuple()
213       : _Inherited() { }
214
215       explicit
216       tuple(const _Elements&... __elements)
217       : _Inherited(__elements...) { }
218
219       template<typename... _UElements>
220         explicit
221         tuple(_UElements&&... __elements)
222         : _Inherited(std::forward<_UElements>(__elements)...) { }
223
224       tuple(const tuple& __in)
225       : _Inherited(__in) { }
226
227       tuple(tuple&& __in)
228       : _Inherited(std::move(__in)) { }
229
230       template<typename... _UElements>
231         tuple(const tuple<_UElements...>& __in)
232         : _Inherited(__in) { }
233
234       template<typename... _UElements>
235         tuple(tuple<_UElements...>&& __in)
236         : _Inherited(std::move(__in)) { }
237
238       tuple&
239       operator=(const tuple& __in)
240       {
241         static_cast<_Inherited&>(*this) = __in;
242         return *this;
243       }
244
245       tuple&
246       operator=(tuple&& __in)
247       {
248         static_cast<_Inherited&>(*this) = std::move(__in);
249         return *this;
250       }
251
252       template<typename... _UElements>
253         tuple&
254         operator=(const tuple<_UElements...>& __in)
255         {
256           static_cast<_Inherited&>(*this) = __in;
257           return *this;
258         }
259
260       template<typename... _UElements>
261         tuple&
262         operator=(tuple<_UElements...>&& __in)
263         {
264           static_cast<_Inherited&>(*this) = std::move(__in);
265           return *this;
266         }
267     };
268
269   template<> class tuple<> { };
270
271   // 2-element tuple, with construction and assignment from a pair.
272   template<typename _T1, typename _T2>
273     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
274     {
275       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
276
277     public:
278       tuple()
279       : _Inherited() { }
280
281       explicit
282       tuple(const _T1& __a1, const _T2& __a2)
283       : _Inherited(__a1, __a2) { }
284
285       template<typename _U1, typename _U2>
286         explicit
287         tuple(_U1&& __a1, _U2&& __a2)
288         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
289
290       tuple(const tuple& __in)
291       : _Inherited(__in) { }
292
293       tuple(tuple&& __in)
294       : _Inherited(std::move(__in)) { }
295
296       template<typename _U1, typename _U2>
297         tuple(const tuple<_U1, _U2>& __in)
298         : _Inherited(__in) { }
299
300       template<typename _U1, typename _U2>
301         tuple(tuple<_U1, _U2>&& __in)
302         : _Inherited(std::move(__in)) { }
303
304       template<typename _U1, typename _U2>
305         tuple(const pair<_U1, _U2>& __in)
306         : _Inherited(_Tuple_impl<0, 
307                      typename __add_c_ref<_U1>::type,
308                      typename __add_c_ref<_U2>::type>(__in.first, 
309                                                       __in.second))
310         { }
311
312       template<typename _U1, typename _U2>
313         tuple(pair<_U1, _U2>&& __in)
314         : _Inherited(_Tuple_impl<0, 
315                      typename std::remove_reference<_U1>::type&&,
316                      typename std::remove_reference<_U2>::type&&>
317                      (std::move(__in.first), std::move(__in.second)))
318         { }
319
320       tuple&
321       operator=(const tuple& __in)
322       {
323         static_cast<_Inherited&>(*this) = __in;
324         return *this;
325       }
326
327       tuple&
328       operator=(tuple&& __in)
329       {
330         static_cast<_Inherited&>(*this) = std::move(__in);
331         return *this;
332       }
333
334       template<typename _U1, typename _U2>
335         tuple&
336         operator=(const tuple<_U1, _U2>& __in)
337         {
338           static_cast<_Inherited&>(*this) = __in;
339           return *this;
340         }
341
342       template<typename _U1, typename _U2>
343         tuple&
344         operator=(tuple<_U1, _U2>&& __in)
345         {
346           static_cast<_Inherited&>(*this) = std::move(__in);
347           return *this;
348         }
349
350       template<typename _U1, typename _U2>
351         tuple&
352         operator=(const pair<_U1, _U2>& __in)
353         {
354           this->_M_head() = __in.first;
355           this->_M_tail()._M_head() = __in.second;
356           return *this;
357         }
358
359       template<typename _U1, typename _U2>
360         tuple&
361         operator=(pair<_U1, _U2>&& __in)
362         {
363           this->_M_head() = std::move(__in.first);
364           this->_M_tail()._M_head() = std::move(__in.second);
365           return *this;
366         }
367     };
368
369
370   /// Gives the type of the ith element of a given tuple type.
371   template<int __i, typename _Tp>
372     struct tuple_element;
373
374   /**
375    * Recursive case for tuple_element: strip off the first element in
376    * the tuple and retrieve the (i-1)th element of the remaining tuple.
377    */
378   template<int __i, typename _Head, typename... _Tail>
379     struct tuple_element<__i, tuple<_Head, _Tail...> >
380     : tuple_element<__i - 1, tuple<_Tail...> > { };
381
382   /**
383    * Basis case for tuple_element: The first element is the one we're seeking.
384    */
385   template<typename _Head, typename... _Tail>
386     struct tuple_element<0, tuple<_Head, _Tail...> >
387     {
388       typedef _Head type;
389     };
390
391   /// Finds the size of a given tuple type.
392   template<typename _Tp>
393     struct tuple_size;
394
395   /// @brief class tuple_size
396   template<typename... _Elements>
397     struct tuple_size<tuple<_Elements...> >
398     {
399       static const int value = sizeof...(_Elements);
400     };
401
402   template<typename... _Elements>
403     const int tuple_size<tuple<_Elements...> >::value;
404
405   template<int __i, typename _Head, typename... _Tail>
406     inline typename __add_ref<_Head>::type
407     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t)
408     { return __t._M_head(); }
409
410   template<int __i, typename _Head, typename... _Tail>
411     inline typename __add_c_ref<_Head>::type
412     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t)
413     { return __t._M_head(); }
414
415   // Return a reference (const reference) to the ith element of a tuple.
416   // Any const or non-const ref elements are returned with their original type.
417   template<int __i, typename... _Elements>
418     inline typename __add_ref<
419                       typename tuple_element<__i, tuple<_Elements...> >::type
420                     >::type
421     get(tuple<_Elements...>& __t)
422     { return __get_helper<__i>(__t); }
423
424   template<int __i, typename... _Elements>
425     inline typename __add_c_ref<
426                       typename tuple_element<__i, tuple<_Elements...> >::type
427                     >::type
428     get(const tuple<_Elements...>& __t)
429     { return __get_helper<__i>(__t); }
430
431   // This class helps construct the various comparison operations on tuples
432   template<int __check_equal_size, int __i, int __j,
433            typename _Tp, typename _Up>
434     struct __tuple_compare;
435
436   template<int __i, int __j, typename _Tp, typename _Up>
437     struct __tuple_compare<0, __i, __j, _Tp, _Up>
438     {
439       static bool __eq(const _Tp& __t, const _Up& __u)
440       {
441         return (get<__i>(__t) == get<__i>(__u) &&
442                 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__eq(__t, __u));
443       }
444      
445       static bool __less(const _Tp& __t, const _Up& __u)
446       {
447         return ((get<__i>(__t) < get<__i>(__u))
448                 || !(get<__i>(__u) < get<__i>(__t)) &&
449                 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__less(__t, __u));
450       }
451     };
452
453   template<int __i, typename _Tp, typename _Up>
454     struct __tuple_compare<0, __i, __i, _Tp, _Up>
455     {
456       static bool __eq(const _Tp&, const _Up&)
457       { return true; }
458      
459       static bool __less(const _Tp&, const _Up&)
460       { return false; }
461     };
462
463   template<typename... _TElements, typename... _UElements>
464     bool
465     operator==(const tuple<_TElements...>& __t,
466                const tuple<_UElements...>& __u)
467     {
468       typedef tuple<_TElements...> _Tp;
469       typedef tuple<_UElements...> _Up;
470       return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
471               0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
472     }
473
474   template<typename... _TElements, typename... _UElements>
475     bool
476     operator<(const tuple<_TElements...>& __t,
477               const tuple<_UElements...>& __u)
478     {
479       typedef tuple<_TElements...> _Tp;
480       typedef tuple<_UElements...> _Up;
481       return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
482               0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
483     }
484
485   template<typename... _TElements, typename... _UElements>
486     inline bool
487     operator!=(const tuple<_TElements...>& __t,
488                const tuple<_UElements...>& __u)
489     { return !(__t == __u); }
490
491   template<typename... _TElements, typename... _UElements>
492     inline bool
493     operator>(const tuple<_TElements...>& __t,
494               const tuple<_UElements...>& __u)
495     { return __u < __t; }
496
497   template<typename... _TElements, typename... _UElements>
498     inline bool
499     operator<=(const tuple<_TElements...>& __t,
500                const tuple<_UElements...>& __u)
501     { return !(__u < __t); }
502
503   template<typename... _TElements, typename... _UElements>
504     inline bool
505     operator>=(const tuple<_TElements...>& __t,
506                const tuple<_UElements...>& __u)
507     { return !(__t < __u); }
508
509   // NB: DR 705.
510   template<typename... _Elements>
511     inline tuple<typename __decay_and_strip<_Elements>::__type...>
512     make_tuple(_Elements&&... __args)
513     {
514       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
515         __result_type;
516       return __result_type(std::forward<_Elements>(__args)...);
517     }
518
519   template<int...> struct __index_holder { };    
520
521   template<int __i, typename _IdxHolder, typename... _Elements>
522     struct __index_holder_impl;
523
524   template<int __i, int... _Indexes, typename _IdxHolder, typename... _Elements>
525     struct __index_holder_impl<__i, __index_holder<_Indexes...>,
526                                _IdxHolder, _Elements...> 
527     {
528       typedef typename __index_holder_impl<__i + 1,
529                                            __index_holder<_Indexes..., __i>,
530                                            _Elements...>::type type;
531     };
532  
533   template<int __i, int... _Indexes>
534     struct __index_holder_impl<__i, __index_holder<_Indexes...> >
535     { typedef __index_holder<_Indexes...> type; };
536
537   template<typename... _Elements>
538     struct __make_index_holder 
539     : __index_holder_impl<0, __index_holder<>, _Elements...> { };
540     
541   template<typename... _TElements, int... _TIdx,
542            typename... _UElements, int... _UIdx> 
543     inline tuple<_TElements..., _UElements...> 
544     __tuple_cat_helper(const tuple<_TElements...>& __t,
545                        const __index_holder<_TIdx...>&,
546                        const tuple<_UElements...>& __u,
547                        const __index_holder<_UIdx...>&)
548     { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
549                                                  get<_UIdx>(__u)...); }
550
551   template<typename... _TElements, int... _TIdx,
552            typename... _UElements, int... _UIdx> 
553     inline tuple<_TElements..., _UElements...> 
554     __tuple_cat_helper(tuple<_TElements...>&& __t,
555                        const __index_holder<_TIdx...>&, 
556                        const tuple<_UElements...>& __u,
557                        const __index_holder<_UIdx...>&)
558     { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
559                                                  get<_UIdx>(__u)...); }
560
561   template<typename... _TElements, int... _TIdx,
562            typename... _UElements, int... _UIdx>
563     inline tuple<_TElements..., _UElements...> 
564     __tuple_cat_helper(const tuple<_TElements...>& __t,
565                        const __index_holder<_TIdx...>&, 
566                        tuple<_UElements...>&& __u,
567                        const __index_holder<_UIdx...>&)
568     { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
569                                                  std::move(get<_UIdx>(__u))...); }
570
571   template<typename... _TElements, int... _TIdx,
572            typename... _UElements, int... _UIdx> 
573     inline tuple<_TElements..., _UElements...> 
574     __tuple_cat_helper(tuple<_TElements...>&& __t,
575                        const __index_holder<_TIdx...>&, 
576                        tuple<_UElements...>&& __u,
577                        const __index_holder<_UIdx...>&)
578     { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
579                                                  std::move(get<_UIdx>(__u))...); }
580
581   template<typename... _TElements, typename... _UElements>
582     inline tuple<_TElements..., _UElements...> 
583     tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u)
584     { 
585       return __tuple_cat_helper(__t, typename
586                                 __make_index_holder<_TElements...>::type(),
587                                 __u, typename
588                                 __make_index_holder<_UElements...>::type());
589     }
590
591   template<typename... _TElements, typename... _UElements>
592     inline tuple<_TElements..., _UElements...> 
593     tuple_cat(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u)
594     {
595       return __tuple_cat_helper(std::move(__t), typename
596                                  __make_index_holder<_TElements...>::type(),
597                                  __u, typename
598                                  __make_index_holder<_UElements...>::type());
599     }
600
601   template<typename... _TElements, typename... _UElements>
602     inline tuple<_TElements..., _UElements...> 
603     tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u)
604     {
605       return __tuple_cat_helper(__t, typename
606                                 __make_index_holder<_TElements...>::type(),
607                                 std::move(__u), typename
608                                 __make_index_holder<_UElements...>::type());
609     }
610
611   template<typename... _TElements, typename... _UElements>
612     inline tuple<_TElements..., _UElements...>
613     tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
614     {
615       return __tuple_cat_helper(std::move(__t), typename
616                                 __make_index_holder<_TElements...>::type(),
617                                 std::move(__u), typename
618                                 __make_index_holder<_UElements...>::type());
619     }
620
621   template<typename... _TElements, typename... _UElements>
622     tuple<_TElements..., _UElements...>
623     operator+(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
624     { return tuple_cat(std::forward<decltype(__t)>(__t),
625                        std::forward<decltype(__u)>(__u)); }
626
627   template<typename... _Elements>
628     inline tuple<_Elements&...>
629     tie(_Elements&... __args)
630     { return tuple<_Elements&...>(__args...); }
631
632   // A class (and instance) which can be used in 'tie' when an element
633   // of a tuple is not required
634   struct _Swallow_assign
635   {
636     template<class _Tp>
637       _Swallow_assign&
638       operator=(const _Tp&)
639       { return *this; }
640   };
641
642   // TODO: Put this in some kind of shared file.
643   namespace
644   {
645     _Swallow_assign ignore;
646   }; // anonymous namespace
647 }
648
649 #endif // _GLIBCXX_CXX0X_TUPLE