OSDN Git Service

2008-01-01 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / std / tuple
1 // <tuple> -*- C++ -*-
2
3 // Copyright (C) 2007 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    * @if maint
105    * Contains the actual implementation of the @c tuple template, stored
106    * as a recursive inheritance hierarchy from the first element (most
107    * derived class) to the last (least derived class). The @c Idx
108    * parameter gives the 0-based index of the element stored at this
109    * point in the hierarchy; we use it to implement a constant-time
110    * get() operation.
111    * @endif
112    */
113   template<int _Idx, typename... _Elements>
114     struct _Tuple_impl; 
115
116   /**
117    * @if maint
118    * Zero-element tuple implementation. This is the basis case for the 
119    * inheritance recursion.
120    * @endif maint
121    */
122   template<int _Idx>
123     struct _Tuple_impl<_Idx> { };
124
125   /**
126    * @if maint
127    * Recursive tuple implementation. Here we store the @c Head element
128    * and derive from a @c Tuple_impl containing the remaining elements
129    * (which contains the @c Tail).
130    * @endif
131    */
132   template<int _Idx, typename _Head, typename... _Tail>
133     struct _Tuple_impl<_Idx, _Head, _Tail...>
134     : public _Tuple_impl<_Idx + 1, _Tail...>,
135       private _Head_base<_Idx, _Head, std::is_empty<_Head>::value>
136     {
137       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
138       typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
139
140       _Head&            _M_head()       { return _Base::_M_head(); }
141       const _Head&      _M_head() const { return _Base::_M_head(); }
142
143       _Inherited&       _M_tail()       { return *this; }
144       const _Inherited& _M_tail() const { return *this; }
145
146       _Tuple_impl()
147       : _Inherited(), _Base() { }
148
149       explicit 
150       _Tuple_impl(typename __add_c_ref<_Head>::type __head,
151                   typename __add_c_ref<_Tail>::type... __tail)
152       : _Inherited(__tail...), _Base(__head) { }
153
154       template<typename _UHead, typename... _UTail> 
155         explicit
156         _Tuple_impl(typename std::remove_reference<_UHead>::type&& __head,
157                     typename std::remove_reference<_UTail>::type&&... __tail)
158         : _Inherited(std::forward<_Inherited>(__tail)...),
159           _Base(std::forward<_Base>(__head)) { }
160
161       _Tuple_impl(const _Tuple_impl& __in)
162       : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
163
164       _Tuple_impl(_Tuple_impl&& __in)
165       : _Inherited(std::forward<_Inherited>(__in._M_tail())),
166         _Base(std::forward<_Base>(__in._M_head())) { }
167
168       template<typename... _UElements>
169         _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
170         : _Inherited(__in._M_tail()), _Base(__in._M_head()) { }
171
172       template<typename... _UElements>
173         _Tuple_impl(_Tuple_impl<_Idx, _UElements...>&& __in)
174         : _Inherited(std::forward<_Inherited>(__in._M_tail())),
175           _Base(std::forward<_Base>(__in._M_head())) { }
176
177       _Tuple_impl&
178       operator=(const _Tuple_impl& __in)
179       {
180         _M_head() = __in._M_head();
181         _M_tail() = __in._M_tail();
182         return *this;
183       }
184
185       _Tuple_impl&
186       operator=(_Tuple_impl&& __in)
187       {
188         _M_head() = std::move(__in._M_head());
189         _M_tail() = std::move(__in._M_tail());
190         return *this;
191       }
192
193       template<typename... _UElements>
194         _Tuple_impl&
195         operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
196         {
197           _M_head() = __in._M_head();
198           _M_tail() = __in._M_tail();
199           return *this;
200         }
201
202       template<typename... _UElements>
203         _Tuple_impl&
204         operator=(_Tuple_impl<_Idx, _UElements...>&& __in)
205         {
206           _M_head() = std::move(__in._M_head());
207           _M_tail() = std::move(__in._M_tail());
208           return *this;
209         }
210     };
211
212   template<typename... _Elements> 
213     class tuple : public _Tuple_impl<0, _Elements...>
214     {
215       typedef _Tuple_impl<0, _Elements...> _Inherited;
216
217     public:
218       tuple()
219       : _Inherited() { }
220
221       explicit
222       tuple(const _Elements&... __elements)
223       : _Inherited(__elements...) { }
224
225       template<typename... _UElements>
226         explicit
227         tuple(_UElements&&... __elements)
228         : _Inherited(std::forward<_UElements>(__elements)...) { }
229
230       tuple(const tuple& __in)
231       : _Inherited(__in) { }
232
233       tuple(tuple&& __in)
234       : _Inherited(std::move(__in)) { }
235
236       template<typename... _UElements>
237         tuple(const tuple<_UElements...>& __in)
238         : _Inherited(__in) { }
239
240       template<typename... _UElements>
241         tuple(tuple<_UElements...>&& __in)
242         : _Inherited(std::move(__in)) { }
243
244       tuple&
245       operator=(const tuple& __in)
246       {
247         static_cast<_Inherited&>(*this) = __in;
248         return *this;
249       }
250
251       tuple&
252       operator=(tuple&& __in)
253       {
254         static_cast<_Inherited&>(*this) = std::move(__in);
255         return *this;
256       }
257
258       template<typename... _UElements>
259         tuple&
260         operator=(const tuple<_UElements...>& __in)
261         {
262           static_cast<_Inherited&>(*this) = __in;
263           return *this;
264         }
265
266       template<typename... _UElements>
267         tuple&
268         operator=(tuple<_UElements...>&& __in)
269         {
270           static_cast<_Inherited&>(*this) = std::move(__in);
271           return *this;
272         }
273     };
274
275   template<> class tuple<> { };
276
277   // 2-element tuple, with construction and assignment from a pair.
278   template<typename _T1, typename _T2>
279     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
280     {
281       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
282
283     public:
284       tuple()
285       : _Inherited() { }
286
287       explicit
288       tuple(const _T1& __a1, const _T2& __a2)
289       : _Inherited(__a1, __a2) { }
290
291       template<typename _U1, typename _U2>
292         explicit
293         tuple(_U1&& __a1, _U2&& __a2)
294         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
295
296       tuple(const tuple& __in)
297       : _Inherited(__in) { }
298
299       tuple(tuple&& __in)
300       : _Inherited(std::move(__in)) { }
301
302       template<typename _U1, typename _U2>
303         tuple(const tuple<_U1, _U2>& __in)
304         : _Inherited(__in) { }
305
306       template<typename _U1, typename _U2>
307         tuple(tuple<_U1, _U2>&& __in)
308         : _Inherited(std::move(__in)) { }
309
310       template<typename _U1, typename _U2>
311         tuple(const pair<_U1, _U2>& __in)
312         : _Inherited(_Tuple_impl<0, 
313                      typename __add_c_ref<_U1>::type,
314                      typename __add_c_ref<_U2>::type>(__in.first, 
315                                                       __in.second))
316         { }
317
318       template<typename _U1, typename _U2>
319         tuple(pair<_U1, _U2>&& __in)
320         : _Inherited(_Tuple_impl<0, 
321                      typename std::remove_reference<_U1>::type&&,
322                      typename std::remove_reference<_U2>::type&&>
323                      (std::move(__in.first), std::move(__in.second)))
324         { }
325
326       tuple&
327       operator=(const tuple& __in)
328       {
329         static_cast<_Inherited&>(*this) = __in;
330         return *this;
331       }
332
333       tuple&
334       operator=(tuple&& __in)
335       {
336         static_cast<_Inherited&>(*this) = std::move(__in);
337         return *this;
338       }
339
340       template<typename _U1, typename _U2>
341         tuple&
342         operator=(const tuple<_U1, _U2>& __in)
343         {
344           static_cast<_Inherited&>(*this) = __in;
345           return *this;
346         }
347
348       template<typename _U1, typename _U2>
349         tuple&
350         operator=(tuple<_U1, _U2>&& __in)
351         {
352           static_cast<_Inherited&>(*this) = std::move(__in);
353           return *this;
354         }
355
356       template<typename _U1, typename _U2>
357         tuple&
358         operator=(const pair<_U1, _U2>& __in)
359         {
360           this->_M_head() = __in.first;
361           this->_M_tail()._M_head() = __in.second;
362           return *this;
363         }
364
365       template<typename _U1, typename _U2>
366         tuple&
367         operator=(pair<_U1, _U2>&& __in)
368         {
369           this->_M_head() = std::move(__in.first);
370           this->_M_tail()._M_head() = std::move(__in.second);
371           return *this;
372         }
373     };
374
375
376   /// Gives the type of the ith element of a given tuple type.
377   template<int __i, typename _Tp>
378     struct tuple_element;
379
380   /**
381    * @if maint
382    * Recursive case for tuple_element: strip off the first element in
383    * the tuple and retrieve the (i-1)th element of the remaining tuple.
384    * @endif
385    */
386   template<int __i, typename _Head, typename... _Tail>
387     struct tuple_element<__i, tuple<_Head, _Tail...> >
388     : tuple_element<__i - 1, tuple<_Tail...> > { };
389
390   /**
391    * @if maint
392    * Basis case for tuple_element: The first element is the one we're seeking.
393    * @endif
394    */
395   template<typename _Head, typename... _Tail>
396     struct tuple_element<0, tuple<_Head, _Tail...> >
397     {
398       typedef _Head type;
399     };
400
401   /// Finds the size of a given tuple type.
402   template<typename _Tp>
403     struct tuple_size;
404
405   /// @brief class tuple_size
406   template<typename... _Elements>
407     struct tuple_size<tuple<_Elements...> >
408     {
409       static const int value = sizeof...(_Elements);
410     };
411
412   template<typename... _Elements>
413     const int tuple_size<tuple<_Elements...> >::value;
414
415   template<int __i, typename _Head, typename... _Tail>
416     inline typename __add_ref<_Head>::type
417     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t)
418     { return __t._M_head(); }
419
420   template<int __i, typename _Head, typename... _Tail>
421     inline typename __add_c_ref<_Head>::type
422     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t)
423     { return __t._M_head(); }
424
425   // Return a reference (const reference) to the ith element of a tuple.
426   // Any const or non-const ref elements are returned with their original type.
427   template<int __i, typename... _Elements>
428     inline typename __add_ref<
429                       typename tuple_element<__i, tuple<_Elements...> >::type
430                     >::type
431     get(tuple<_Elements...>& __t)
432     { return __get_helper<__i>(__t); }
433
434   template<int __i, typename... _Elements>
435     inline typename __add_c_ref<
436                       typename tuple_element<__i, tuple<_Elements...> >::type
437                     >::type
438     get(const tuple<_Elements...>& __t)
439     { return __get_helper<__i>(__t); }
440
441   // This class helps construct the various comparison operations on tuples
442   template<int __check_equal_size, int __i, int __j,
443            typename _Tp, typename _Up>
444     struct __tuple_compare;
445
446   template<int __i, int __j, typename _Tp, typename _Up>
447     struct __tuple_compare<0, __i, __j, _Tp, _Up>
448     {
449       static bool __eq(const _Tp& __t, const _Up& __u)
450       {
451         return (get<__i>(__t) == get<__i>(__u) &&
452                 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__eq(__t, __u));
453       }
454      
455       static bool __less(const _Tp& __t, const _Up& __u)
456       {
457         return ((get<__i>(__t) < get<__i>(__u))
458                 || !(get<__i>(__u) < get<__i>(__t)) &&
459                 __tuple_compare<0, __i+1, __j, _Tp, _Up>::__less(__t, __u));
460       }
461     };
462
463   template<int __i, typename _Tp, typename _Up>
464     struct __tuple_compare<0, __i, __i, _Tp, _Up>
465     {
466       static bool __eq(const _Tp&, const _Up&)
467       { return true; }
468      
469       static bool __less(const _Tp&, const _Up&)
470       { return false; }
471     };
472
473   template<typename... _TElements, typename... _UElements>
474     bool
475     operator==(const tuple<_TElements...>& __t,
476                const tuple<_UElements...>& __u)
477     {
478       typedef tuple<_TElements...> _Tp;
479       typedef tuple<_UElements...> _Up;
480       return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
481               0, tuple_size<_Tp>::value, _Tp, _Up>::__eq(__t, __u));
482     }
483
484   template<typename... _TElements, typename... _UElements>
485     bool
486     operator<(const tuple<_TElements...>& __t,
487               const tuple<_UElements...>& __u)
488     {
489       typedef tuple<_TElements...> _Tp;
490       typedef tuple<_UElements...> _Up;
491       return (__tuple_compare<tuple_size<_Tp>::value - tuple_size<_Tp>::value,
492               0, tuple_size<_Tp>::value, _Tp, _Up>::__less(__t, __u));
493     }
494
495   template<typename... _TElements, typename... _UElements>
496     inline bool
497     operator!=(const tuple<_TElements...>& __t,
498                const tuple<_UElements...>& __u)
499     { return !(__t == __u); }
500
501   template<typename... _TElements, typename... _UElements>
502     inline bool
503     operator>(const tuple<_TElements...>& __t,
504               const tuple<_UElements...>& __u)
505     { return __u < __t; }
506
507   template<typename... _TElements, typename... _UElements>
508     inline bool
509     operator<=(const tuple<_TElements...>& __t,
510                const tuple<_UElements...>& __u)
511     { return !(__u < __t); }
512
513   template<typename... _TElements, typename... _UElements>
514     inline bool
515     operator>=(const tuple<_TElements...>& __t,
516                const tuple<_UElements...>& __u)
517     { return !(__t < __u); }
518
519   // NB: DR 705.
520   template<typename... _Elements>
521     inline tuple<typename __decay_and_strip<_Elements>::__type...>
522     make_tuple(_Elements&&... __args)
523     {
524       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
525         __result_type;
526       return __result_type(std::forward<_Elements>(__args)...);
527     }
528
529   template<int...> struct __index_holder { };    
530
531   template<int __i, typename _IdxHolder, typename... _Elements>
532     struct __index_holder_impl;
533
534   template<int __i, int... _Indexes, typename _IdxHolder, typename... _Elements>
535     struct __index_holder_impl<__i, __index_holder<_Indexes...>,
536                                _IdxHolder, _Elements...> 
537     {
538       typedef typename __index_holder_impl<__i + 1,
539                                            __index_holder<_Indexes..., __i>,
540                                            _Elements...>::type type;
541     };
542  
543   template<int __i, int... _Indexes>
544     struct __index_holder_impl<__i, __index_holder<_Indexes...> >
545     { typedef __index_holder<_Indexes...> type; };
546
547   template<typename... _Elements>
548     struct __make_index_holder 
549     : __index_holder_impl<0, __index_holder<>, _Elements...> { };
550     
551   template<typename... _TElements, int... _TIdx,
552            typename... _UElements, int... _UIdx> 
553     inline tuple<_TElements..., _UElements...> 
554     __tuple_cat_helper(const tuple<_TElements...>& __t,
555                        const __index_holder<_TIdx...>&,
556                        const tuple<_UElements...>& __u,
557                        const __index_holder<_UIdx...>&)
558     { return tuple<_TElements..., _UElements...>(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(tuple<_TElements...>&& __t,
565                        const __index_holder<_TIdx...>&, 
566                        const tuple<_UElements...>& __u,
567                        const __index_holder<_UIdx...>&)
568     { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
569                                                  get<_UIdx>(__u)...); }
570
571   template<typename... _TElements, int... _TIdx,
572            typename... _UElements, int... _UIdx>
573     inline tuple<_TElements..., _UElements...> 
574     __tuple_cat_helper(const tuple<_TElements...>& __t,
575                        const __index_holder<_TIdx...>&, 
576                        tuple<_UElements...>&& __u,
577                        const __index_holder<_UIdx...>&)
578     { return tuple<_TElements..., _UElements...>(get<_TIdx>(__t)...,
579                                                  std::move(get<_UIdx>(__u))...); }
580
581   template<typename... _TElements, int... _TIdx,
582            typename... _UElements, int... _UIdx> 
583     inline tuple<_TElements..., _UElements...> 
584     __tuple_cat_helper(tuple<_TElements...>&& __t,
585                        const __index_holder<_TIdx...>&, 
586                        tuple<_UElements...>&& __u,
587                        const __index_holder<_UIdx...>&)
588     { return tuple<_TElements..., _UElements...>(std::move(get<_TIdx>(__t))...,
589                                                  std::move(get<_UIdx>(__u))...); }
590
591   template<typename... _TElements, typename... _UElements>
592     inline tuple<_TElements..., _UElements...> 
593     tuple_cat(const tuple<_TElements...>& __t, const tuple<_UElements...>& __u)
594     { 
595       return __tuple_cat_helper(__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(tuple<_TElements...>&& __t, const tuple<_UElements...>& __u)
604     {
605       return __tuple_cat_helper(std::move(__t), typename
606                                  __make_index_holder<_TElements...>::type(),
607                                  __u, typename
608                                  __make_index_holder<_UElements...>::type());
609     }
610
611   template<typename... _TElements, typename... _UElements>
612     inline tuple<_TElements..., _UElements...> 
613     tuple_cat(const tuple<_TElements...>& __t, tuple<_UElements...>&& __u)
614     {
615       return __tuple_cat_helper(__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     inline tuple<_TElements..., _UElements...>
623     tuple_cat(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
624     {
625       return __tuple_cat_helper(std::move(__t), typename
626                                 __make_index_holder<_TElements...>::type(),
627                                 std::move(__u), typename
628                                 __make_index_holder<_UElements...>::type());
629     }
630
631   template<typename... _TElements, typename... _UElements>
632     tuple<_TElements..., _UElements...>
633     operator+(tuple<_TElements...>&& __t, tuple<_UElements...>&& __u)
634     { return tuple_cat(std::forward<decltype(__t)>(__t),
635                        std::forward<decltype(__u)>(__u)); }
636
637   template<typename... _Elements>
638     inline tuple<_Elements&...>
639     tie(_Elements&... __args)
640     { return tuple<_Elements&...>(__args...); }
641
642   // A class (and instance) which can be used in 'tie' when an element
643   // of a tuple is not required
644   struct _Swallow_assign
645   {
646     template<class _Tp>
647       _Swallow_assign&
648       operator=(const _Tp&)
649       { return *this; }
650   };
651
652   // TODO: Put this in some kind of shared file.
653   namespace
654   {
655     _Swallow_assign ignore;
656   }; // anonymous namespace
657 }
658
659 #endif // _GLIBCXX_CXX0X_TUPLE