source: NonGTP/Boost/boost/lambda/detail/operator_return_type_traits.hpp @ 857

Revision 857, 29.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1//  operator_return_type_traits.hpp -- Boost Lambda Library ------------------
2
3// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
4//
5// Distributed under the Boost Software License, Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// For more information, see www.boost.org
10
11#ifndef BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
12#define BOOST_LAMBDA_OPERATOR_RETURN_TYPE_TRAITS_HPP
13
14#include "boost/lambda/detail/is_instance_of.hpp"
15#include "boost/type_traits/same_traits.hpp"
16
17#include "boost/indirect_reference.hpp"
18
19#include <cstddef> // needed for the ptrdiff_t
20#include <iosfwd>  // for istream and ostream
21
22#include <iterator> // needed for operator&
23
24namespace boost {
25namespace lambda {
26namespace detail {
27
28// -- general helper templates for type deduction ------------------
29
30// Much of the type deduction code for standard arithmetic types from Gary Powell
31
32template <class A> struct promote_code { static const int value = -1; };
33// this means that a code is not defined for A
34
35// -- the next 5 types are needed in if_then_else_return
36// the promotion order is not important, but they must have distinct values.
37template <> struct promote_code<bool> { static const int value = 10; };
38template <> struct promote_code<char> { static const int value = 20; };
39template <> struct promote_code<unsigned char> { static const int value = 30; };
40template <> struct promote_code<signed char> { static const int value = 40; };
41template <> struct promote_code<short int> { static const int value = 50; };
42// ----------
43
44template <> struct promote_code<int> { static const int value = 100; };
45template <> struct promote_code<unsigned int> { static const int value = 200; };
46template <> struct promote_code<long> { static const int value = 300; };
47template <> struct promote_code<unsigned long> { static const int value = 400; };
48
49template <> struct promote_code<float> { static const int value = 500; };
50template <> struct promote_code<double> { static const int value = 600; };
51template <> struct promote_code<long double> { static const int value = 700; };
52
53// TODO: wchar_t
54
55// forward delcaration of complex.
56
57} // namespace detail
58} // namespace lambda
59} // namespace boost
60
61namespace std {
62  template<class T> class complex;
63}
64
65namespace boost {
66namespace lambda {
67namespace detail {
68
69template <> struct promote_code< std::complex<float> > { static const int value = 800; };
70template <> struct promote_code< std::complex<double> > { static const int value = 900; };
71template <> struct promote_code< std::complex<long double> > { static const int value = 1000; };
72
73// -- int promotion -------------------------------------------
74template <class T> struct promote_to_int { typedef T type; };
75
76template <> struct promote_to_int<bool> { typedef int type; };
77template <> struct promote_to_int<char> { typedef int type; };
78template <> struct promote_to_int<unsigned char> { typedef int type; };
79template <> struct promote_to_int<signed char> { typedef int type; };
80template <> struct promote_to_int<short int> { typedef int type; };
81
82// The unsigned short int promotion rule is this:
83// unsigned short int to signed int if a signed int can hold all values
84// of unsigned short int, otherwise go to unsigned int.
85template <> struct promote_to_int<unsigned short int>
86{
87        typedef
88                detail::IF<sizeof(int) <= sizeof(unsigned short int),       
89// I had the logic reversed but ">" messes up the parsing.
90                unsigned int,
91                int>::RET type;
92};
93
94
95// TODO: think, should there be default behaviour for non-standard types?
96
97} // namespace detail
98
99// ------------------------------------------
100// Unary actions ----------------------------
101// ------------------------------------------
102
103template<class Act, class A>
104struct plain_return_type_1 {
105  typedef detail::unspecified type;
106};
107
108
109
110template<class Act, class A>
111struct plain_return_type_1<unary_arithmetic_action<Act>, A> {
112  typedef A type;
113};
114
115template<class Act, class A>
116struct return_type_1<unary_arithmetic_action<Act>, A> {
117  typedef
118    typename plain_return_type_1<
119      unary_arithmetic_action<Act>,
120      typename detail::remove_reference_and_cv<A>::type
121    >::type type;
122};
123
124
125template<class A>
126struct plain_return_type_1<bitwise_action<not_action>, A> {
127  typedef A type;
128};
129
130// bitwise not, operator~()
131template<class A> struct return_type_1<bitwise_action<not_action>, A> {
132  typedef
133    typename plain_return_type_1<
134      bitwise_action<not_action>,
135      typename detail::remove_reference_and_cv<A>::type
136    >::type type;
137};
138
139
140// prefix increment and decrement operators return
141// their argument by default as a non-const reference
142template<class Act, class A>
143struct plain_return_type_1<pre_increment_decrement_action<Act>, A> {
144  typedef A& type;
145};
146
147template<class Act, class A>
148struct return_type_1<pre_increment_decrement_action<Act>, A> {
149  typedef
150    typename plain_return_type_1<
151      pre_increment_decrement_action<Act>,
152      typename detail::remove_reference_and_cv<A>::type
153    >::type type;
154};
155
156// post decrement just returns the same plain type.
157template<class Act, class A>
158struct plain_return_type_1<post_increment_decrement_action<Act>, A> {
159  typedef A type;
160};
161
162template<class Act, class A>
163struct return_type_1<post_increment_decrement_action<Act>, A>
164{
165  typedef
166    typename plain_return_type_1<
167      post_increment_decrement_action<Act>,
168      typename detail::remove_reference_and_cv<A>::type
169    >::type type;
170};
171
172// logical not, operator!()
173template<class A>
174struct plain_return_type_1<logical_action<not_action>, A> {
175  typedef bool type;
176};
177
178template<class A>
179struct return_type_1<logical_action<not_action>, A> {
180  typedef
181    typename plain_return_type_1<
182      logical_action<not_action>,
183      typename detail::remove_reference_and_cv<A>::type
184    >::type type;
185};
186
187// address of action ---------------------------------------
188
189
190template<class A>
191struct return_type_1<other_action<addressof_action>, A> {
192  typedef
193    typename plain_return_type_1<
194      other_action<addressof_action>,
195      typename detail::remove_reference_and_cv<A>::type
196    >::type type1;
197
198  // If no user defined specialization for A, then return the
199  // cv qualified pointer to A
200  typedef typename detail::IF<
201    boost::is_same<type1, detail::unspecified>::value,
202    typename boost::remove_reference<A>::type*,
203    type1
204  >::RET type;
205};
206
207// contentsof action ------------------------------------
208
209// TODO: this deduction may lead to fail directly,
210// (if A has no specialization for iterator_traits and has no
211// typedef A::reference.
212// There is no easy way around this, cause there doesn't seem to be a way
213// to test whether a class is an iterator or not.
214 
215// The default works with std::iterators.
216
217namespace detail {
218
219  // A is a nonreference type
220template <class A> struct contentsof_type {
221  typedef typename boost::indirect_reference<A>::type type;
222};
223
224  // this is since the nullary () in lambda_functor is always instantiated
225template <> struct contentsof_type<null_type> {
226  typedef detail::unspecified type;
227};
228
229
230template <class A> struct contentsof_type<const A> {
231  typedef typename contentsof_type<A>::type type1;
232  // return a reference to the underlying const type
233  // the IF is because the A::reference in the primary template could
234  // be some class type rather than a real reference, hence
235  // we do not want to make it a reference here either
236    typedef typename detail::IF<
237      is_reference<type1>::value,
238      const typename boost::remove_reference<type1>::type &,
239      const type1
240  >::RET type;
241};
242
243template <class A> struct contentsof_type<volatile A> {
244  typedef typename contentsof_type<A>::type type1;
245  typedef typename detail::IF<
246    is_reference<type1>::value,
247    volatile typename boost::remove_reference<type1>::type &,
248    volatile type1
249  >::RET type;
250};
251
252template <class A> struct contentsof_type<const volatile A> {
253  typedef typename contentsof_type<A>::type type1;
254  typedef typename detail::IF<
255    is_reference<type1>::value,
256    const volatile typename boost::remove_reference<type1>::type &,
257    const volatile type1
258  >::RET type;
259};
260
261  // standard iterator traits should take care of the pointer types
262  // but just to be on the safe side, we have the specializations here:
263  // these work even if A is cv-qualified.
264template <class A> struct contentsof_type<A*> {
265  typedef A& type;
266};
267template <class A> struct contentsof_type<A* const> {
268  typedef A& type;
269};
270template <class A> struct contentsof_type<A* volatile> {
271  typedef A& type;
272};
273template <class A> struct contentsof_type<A* const volatile> {
274  typedef A& type;
275};
276
277template<class A, int N> struct contentsof_type<A[N]> {
278  typedef A& type;
279};
280template<class A, int N> struct contentsof_type<const A[N]> {
281  typedef const A& type;
282};
283template<class A, int N> struct contentsof_type<volatile A[N]> {
284  typedef volatile A& type;
285};
286template<class A, int N> struct contentsof_type<const volatile A[N]> {
287  typedef const volatile A& type;
288};
289
290
291
292
293
294} // end detail
295
296template<class A>
297struct return_type_1<other_action<contentsof_action>, A> {
298
299  typedef
300    typename plain_return_type_1<
301      other_action<contentsof_action>,
302      typename detail::remove_reference_and_cv<A>::type
303    >::type type1;
304
305  // If no user defined specialization for A, then return the
306  // cv qualified pointer to A
307  typedef typename
308  detail::IF_type<
309    boost::is_same<type1, detail::unspecified>::value,
310    detail::contentsof_type<
311      typename boost::remove_reference<A>::type
312    >,
313    detail::identity_mapping<type1>
314  >::type type;
315};
316
317
318// ------------------------------------------------------------------
319// binary actions ---------------------------------------------------
320// ------------------------------------------------------------------
321
322// here the default case is: no user defined versions:
323template <class Act, class A, class B>
324struct plain_return_type_2 {
325  typedef detail::unspecified type;
326};
327
328namespace detail {
329
330// error classes
331class illegal_pointer_arithmetic{};
332
333// pointer arithmetic type deductions ----------------------
334// value = false means that this is not a pointer arithmetic case
335// value = true means, that this can be a pointer arithmetic case, but not necessarily is
336// This means, that for user defined operators for pointer types, say for some operator+(X, *Y),
337// the deductions must be coded at an earliel level (return_type_2).
338
339template<class Act, class A, class B>
340struct pointer_arithmetic_traits { static const bool value = false; };
341
342template<class A, class B>
343struct pointer_arithmetic_traits<plus_action, A, B> {
344
345  typedef typename
346    array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
347  typedef typename
348    array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
349
350  static const bool is_pointer_A = boost::is_pointer<AP>::value;
351  static const bool is_pointer_B = boost::is_pointer<BP>::value; 
352
353  static const bool value = is_pointer_A || is_pointer_B;
354
355  // can't add two pointers.
356  // note, that we do not check wether the other type is valid for
357  // addition with a pointer.
358  // the compiler will catch it in the apply function
359
360  typedef typename
361  detail::IF<
362    is_pointer_A && is_pointer_B,
363      detail::return_type_deduction_failure<
364        detail::illegal_pointer_arithmetic
365      >,
366      typename detail::IF<is_pointer_A, AP, BP>::RET
367  >::RET type;
368
369};
370
371template<class A, class B>
372struct pointer_arithmetic_traits<minus_action, A, B> {
373  typedef typename
374    array_to_pointer<typename boost::remove_reference<A>::type>::type AP;
375  typedef typename
376    array_to_pointer<typename boost::remove_reference<B>::type>::type BP;
377
378  static const bool is_pointer_A = boost::is_pointer<AP>::value;
379  static const bool is_pointer_B = boost::is_pointer<BP>::value; 
380
381  static const bool value = is_pointer_A || is_pointer_B;
382
383  static const bool same_pointer_type =
384    is_pointer_A && is_pointer_B &&
385    boost::is_same<
386      typename boost::remove_const<
387        typename boost::remove_pointer<
388          typename boost::remove_const<AP>::type
389        >::type
390      >::type,
391      typename boost::remove_const<
392        typename boost::remove_pointer<
393          typename boost::remove_const<BP>::type
394        >::type
395      >::type
396    >::value;
397
398  // ptr - ptr has type ptrdiff_t
399  // note, that we do not check if, in ptr - B, B is
400  // valid for subtraction with a pointer.
401  // the compiler will catch it in the apply function
402
403  typedef typename
404  detail::IF<
405    same_pointer_type, const std::ptrdiff_t,
406    typename detail::IF<
407      is_pointer_A,
408      AP,
409      detail::return_type_deduction_failure<detail::illegal_pointer_arithmetic>
410    >::RET
411  >::RET type;
412};
413
414} // namespace detail
415   
416// -- arithmetic actions ---------------------------------------------
417
418namespace detail {
419   
420template<bool is_pointer_arithmetic, class Act, class A, class B>
421struct return_type_2_arithmetic_phase_1;
422
423template<class A, class B> struct return_type_2_arithmetic_phase_2;
424template<class A, class B> struct return_type_2_arithmetic_phase_3;
425
426} // namespace detail
427 
428
429// drop any qualifiers from the argument types within arithmetic_action
430template<class A, class B, class Act>
431struct return_type_2<arithmetic_action<Act>, A, B>
432{
433  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
434  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
435
436  typedef typename
437    plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>::type type1;
438 
439  // if user defined return type, do not enter the whole arithmetic deductions
440  typedef typename
441    detail::IF_type<
442      boost::is_same<type1, detail::unspecified>::value,
443      detail::return_type_2_arithmetic_phase_1<
444         detail::pointer_arithmetic_traits<Act, A, B>::value, Act, A, B
445      >,
446      plain_return_type_2<arithmetic_action<Act>, plain_A, plain_B>
447    >::type type;
448};
449
450namespace detail {
451   
452// perform integral promotion, no pointer arithmetic
453template<bool is_pointer_arithmetic, class Act, class A, class B>
454struct return_type_2_arithmetic_phase_1
455{
456  typedef typename
457    return_type_2_arithmetic_phase_2<
458      typename remove_reference_and_cv<A>::type,
459      typename remove_reference_and_cv<B>::type
460    >::type type;
461};
462
463// pointer_arithmetic
464template<class Act, class A, class B>
465struct return_type_2_arithmetic_phase_1<true, Act, A, B>
466{
467  typedef typename
468    pointer_arithmetic_traits<Act, A, B>::type type;
469};
470
471template<class A, class B>
472struct return_type_2_arithmetic_phase_2 {
473  typedef typename
474    return_type_2_arithmetic_phase_3<
475      typename promote_to_int<A>::type,
476      typename promote_to_int<B>::type
477    >::type type;
478};
479
480// specialization for unsigned int.
481// We only have to do these two specialization because the value promotion will
482// take care of the other cases.
483// The unsigned int promotion rule is this:
484// unsigned int to long if a long can hold all values of unsigned int,
485// otherwise go to unsigned long.
486
487// struct so I don't have to type this twice.
488struct promotion_of_unsigned_int
489{
490        typedef
491        detail::IF<sizeof(long) <= sizeof(unsigned int),       
492                unsigned long,
493                long>::RET type;
494};
495
496template<>
497struct return_type_2_arithmetic_phase_2<unsigned int, long>
498{
499        typedef promotion_of_unsigned_int::type type;
500};
501template<>
502struct return_type_2_arithmetic_phase_2<long, unsigned int>
503{
504        typedef promotion_of_unsigned_int::type type;
505};
506
507
508template<class A, class B> struct return_type_2_arithmetic_phase_3 {
509   enum { promote_code_A_value = promote_code<A>::value,
510         promote_code_B_value = promote_code<B>::value }; // enums for KCC
511  typedef typename
512    detail::IF<
513      promote_code_A_value == -1 || promote_code_B_value == -1,
514      detail::return_type_deduction_failure<return_type_2_arithmetic_phase_3>,
515      typename detail::IF<
516        ((int)promote_code_A_value > (int)promote_code_B_value),
517        A,
518        B
519      >::RET
520    >::RET type;                   
521};
522
523} // namespace detail
524
525// --  bitwise actions -------------------------------------------
526// note: for integral types deuduction is similar to arithmetic actions.
527
528// drop any qualifiers from the argument types within arithmetic action
529template<class A, class B, class Act>
530struct return_type_2<bitwise_action<Act>, A, B>
531{
532
533  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
534  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
535
536  typedef typename
537    plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>::type type1;
538 
539  // if user defined return type, do not enter type deductions
540  typedef typename
541    detail::IF_type<
542      boost::is_same<type1, detail::unspecified>::value,
543      return_type_2<arithmetic_action<plus_action>, A, B>,
544      plain_return_type_2<bitwise_action<Act>, plain_A, plain_B>
545    >::type type;
546
547  // plus_action is just a random pick, has to be a concrete instance
548
549  // TODO: This check is only valid for built-in types, overloaded types might
550  // accept floating point operators
551
552  // bitwise operators not defined for floating point types
553  // these test are not strictly needed here, since the error will be caught in
554  // the apply function
555  BOOST_STATIC_ASSERT(!(boost::is_float<plain_A>::value && boost::is_float<plain_B>::value));
556
557};
558
559namespace detail {
560
561#ifdef BOOST_NO_TEMPLATED_STREAMS
562
563template<class A, class B>
564struct leftshift_type {
565
566  typedef typename detail::IF<
567    boost::is_convertible<
568      typename boost::remove_reference<A>::type*,
569      std::ostream*
570    >::value,
571    std::ostream&,
572    typename detail::remove_reference_and_cv<A>::type
573  >::RET type;
574};
575
576template<class A, class B>
577struct rightshift_type {
578
579  typedef typename detail::IF<
580
581    boost::is_convertible<
582      typename boost::remove_reference<A>::type*,
583      std::istream*
584    >::value,
585    std::istream&,
586    typename detail::remove_reference_and_cv<A>::type
587  >::RET type;
588};
589
590#else
591
592template <class T> struct get_ostream_type {
593  typedef std::basic_ostream<typename T::char_type,
594                             typename T::traits_type>& type;
595};
596
597template <class T> struct get_istream_type {
598  typedef std::basic_istream<typename T::char_type,
599                             typename T::traits_type>& type;
600};
601
602template<class A, class B>
603struct leftshift_type {
604private:
605  typedef typename boost::remove_reference<A>::type plainA;
606public:
607  typedef typename detail::IF_type<
608    is_instance_of_2<plainA, std::basic_ostream>::value,
609    get_ostream_type<plainA>, //reference to the stream
610    detail::remove_reference_and_cv<A>
611  >::type type;
612};
613
614template<class A, class B>
615struct rightshift_type {
616private:
617  typedef typename boost::remove_reference<A>::type plainA;
618public:
619  typedef typename detail::IF_type<
620    is_instance_of_2<plainA, std::basic_istream>::value,
621    get_istream_type<plainA>, //reference to the stream
622    detail::remove_reference_and_cv<A>
623  >::type type;
624};
625
626
627#endif
628
629} // end detail
630
631// ostream
632template<class A, class B>
633struct return_type_2<bitwise_action<leftshift_action>, A, B>
634{
635  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
636  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
637
638  typedef typename
639    plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>::type type1;
640 
641  // if user defined return type, do not enter type deductions
642  typedef typename
643    detail::IF_type<
644      boost::is_same<type1, detail::unspecified>::value,
645      detail::leftshift_type<A, B>,
646      plain_return_type_2<bitwise_action<leftshift_action>, plain_A, plain_B>
647    >::type type;
648};
649
650// istream
651template<class A, class B>
652struct return_type_2<bitwise_action<rightshift_action>, A, B>
653{
654  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
655  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
656
657  typedef typename
658    plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>::type type1;
659 
660  // if user defined return type, do not enter type deductions
661  typedef typename
662    detail::IF_type<
663      boost::is_same<type1, detail::unspecified>::value,
664      detail::rightshift_type<A, B>,
665      plain_return_type_2<bitwise_action<rightshift_action>, plain_A, plain_B>
666    >::type type;
667};
668
669// -- logical actions ----------------------------------------
670// always bool
671// NOTE: this may not be true for some weird user-defined types,
672template<class A, class B, class Act>
673struct plain_return_type_2<logical_action<Act>, A, B> {
674  typedef bool type;
675};
676
677template<class A, class B, class Act>
678struct return_type_2<logical_action<Act>, A, B> {
679
680  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
681  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
682
683  typedef typename
684    plain_return_type_2<logical_action<Act>, plain_A, plain_B>::type type;
685 
686};
687
688
689// -- relational actions ----------------------------------------
690// always bool
691// NOTE: this may not be true for some weird user-defined types,
692template<class A, class B, class Act>
693struct plain_return_type_2<relational_action<Act>, A, B> {
694  typedef bool type;
695};
696
697template<class A, class B, class Act>
698struct return_type_2<relational_action<Act>, A, B> {
699
700  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
701  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
702
703  typedef typename
704    plain_return_type_2<relational_action<Act>, plain_A, plain_B>::type type;
705};
706
707// Assingment actions -----------------------------------------------
708// return type is the type of the first argument as reference
709
710// note that cv-qualifiers are preserved.
711// Yes, assignment operator can be const!
712
713// NOTE: this may not be true for some weird user-defined types,
714
715template<class A, class B, class Act>
716struct return_type_2<arithmetic_assignment_action<Act>, A, B> {
717
718  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
719  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
720
721  typedef typename
722    plain_return_type_2<
723      arithmetic_assignment_action<Act>, plain_A, plain_B
724    >::type type1;
725 
726  typedef typename
727    detail::IF<
728      boost::is_same<type1, detail::unspecified>::value,
729      typename boost::add_reference<A>::type,
730      type1
731    >::RET type;
732};
733
734template<class A, class B, class Act>
735struct return_type_2<bitwise_assignment_action<Act>, A, B> {
736
737  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
738  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
739
740  typedef typename
741    plain_return_type_2<
742      bitwise_assignment_action<Act>, plain_A, plain_B
743    >::type type1;
744 
745  typedef typename
746    detail::IF<
747      boost::is_same<type1, detail::unspecified>::value,
748      typename boost::add_reference<A>::type,
749      type1
750    >::RET type;
751};
752
753template<class A, class B>
754struct return_type_2<other_action<assignment_action>, A, B> {
755  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
756  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
757
758  typedef typename
759    plain_return_type_2<
760      other_action<assignment_action>, plain_A, plain_B
761    >::type type1;
762 
763  typedef typename
764    detail::IF<
765      boost::is_same<type1, detail::unspecified>::value,
766      typename boost::add_reference<A>::type,
767      type1
768    >::RET type;
769};
770
771// -- other actions ----------------------------------------
772
773// comma action ----------------------------------
774// Note: this may not be true for some weird user-defined types,
775
776// NOTE! This only tries the plain_return_type_2 layer and gives
777// detail::unspecified as default. If no such specialization is found, the
778// type rule in the spcecialization of the return_type_2_prot is used
779// to give the type of the right argument (which can be a reference too)
780// (The built in operator, can return a l- or rvalue).
781template<class A, class B>
782struct return_type_2<other_action<comma_action>, A, B> {
783
784  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
785  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
786
787  typedef typename
788    plain_return_type_2<
789      other_action<comma_action>, plain_A, plain_B
790    >::type type;
791  };
792
793// subscript action -----------------------------------------------
794
795
796namespace detail {
797  // A and B are nonreference types
798template <class A, class B> struct subscript_type {
799  typedef detail::unspecified type;
800};
801
802template <class A, class B> struct subscript_type<A*, B> {
803  typedef A& type;
804};
805template <class A, class B> struct subscript_type<A* const, B> {
806  typedef A& type;
807};
808template <class A, class B> struct subscript_type<A* volatile, B> {
809  typedef A& type;
810};
811template <class A, class B> struct subscript_type<A* const volatile, B> {
812  typedef A& type;
813};
814
815
816template<class A, class B, int N> struct subscript_type<A[N], B> {
817  typedef A& type;
818};
819
820  // these 3 specializations are needed to make gcc <3 happy
821template<class A, class B, int N> struct subscript_type<const A[N], B> {
822  typedef const A& type;
823};
824template<class A, class B, int N> struct subscript_type<volatile A[N], B> {
825  typedef volatile A& type;
826};
827template<class A, class B, int N> struct subscript_type<const volatile A[N], B> {
828  typedef const volatile A& type;
829};
830
831} // end detail
832
833template<class A, class B>
834struct return_type_2<other_action<subscript_action>, A, B> {
835
836  typedef typename detail::remove_reference_and_cv<A>::type plain_A;
837  typedef typename detail::remove_reference_and_cv<B>::type plain_B;
838
839  typedef typename boost::remove_reference<A>::type nonref_A;
840  typedef typename boost::remove_reference<B>::type nonref_B;
841
842  typedef typename
843    plain_return_type_2<
844      other_action<subscript_action>, plain_A, plain_B
845    >::type type1;
846 
847  typedef typename
848    detail::IF_type<
849      boost::is_same<type1, detail::unspecified>::value,
850      detail::subscript_type<nonref_A, nonref_B>,
851      plain_return_type_2<other_action<subscript_action>, plain_A, plain_B>
852    >::type type;
853
854};
855
856
857} // namespace lambda
858} // namespace boost
859
860
861// Forward declarations are incompatible with the libstdc++ debug mode.
862#if BOOST_WORKAROUND(__GNUC__, >= 3) && _GLIBCXX_DEBUG
863#include <string>
864#include <vector>
865#include <map>
866#include <deque>
867#else
868
869// The GCC 2.95.x uses a non-conformant deque
870#if BOOST_WORKAROUND(__GNUC__, == 2) && __GNUC_MINOR__ <= 96
871#include <deque>
872#else
873
874namespace std {
875  template <class T, class Allocator> class deque;
876}
877
878#endif
879
880namespace std {
881 template <class Char, class Traits, class Allocator> class basic_string;
882 template <class T, class Allocator> class vector;
883 template <class Key, class T, class Cmp, class Allocator> class map;
884 template <class Key, class T, class Cmp, class Allocator> class multimap;
885}
886
887#endif
888
889
890
891namespace boost {
892namespace lambda {
893
894template<class Key, class T, class Cmp, class Allocator, class B>
895struct plain_return_type_2<other_action<subscript_action>, std::map<Key, T, Cmp, Allocator>, B> {
896  typedef T& type;
897  // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
898};
899
900template<class Key, class T, class Cmp, class Allocator, class B>
901struct plain_return_type_2<other_action<subscript_action>, std::multimap<Key, T, Cmp, Allocator>, B> {
902  typedef T& type;
903  // T == std::map<Key, T, Cmp, Allocator>::mapped_type;
904};
905
906  // deque
907template<class T, class Allocator, class B>
908struct plain_return_type_2<other_action<subscript_action>, std::deque<T, Allocator>, B> {
909  typedef typename std::deque<T, Allocator>::reference type;
910};
911template<class T, class Allocator, class B>
912struct plain_return_type_2<other_action<subscript_action>, const std::deque<T, Allocator>, B> {
913  typedef typename std::deque<T, Allocator>::const_reference type;
914};
915
916  // vector
917template<class T, class Allocator, class B>
918struct plain_return_type_2<other_action<subscript_action>, std::vector<T, Allocator>, B> {
919  typedef typename std::vector<T, Allocator>::reference type;
920};
921template<class T, class Allocator, class B>
922struct plain_return_type_2<other_action<subscript_action>, const std::vector<T, Allocator>, B> {
923  typedef typename std::vector<T, Allocator>::const_reference type;
924};
925
926  // basic_string
927template<class Char, class Traits, class Allocator, class B>
928struct plain_return_type_2<other_action<subscript_action>, std::basic_string<Char, Traits, Allocator>, B> {
929  typedef typename std::basic_string<Char, Traits, Allocator>::reference type;
930};
931template<class Char, class Traits, class Allocator, class B>
932struct plain_return_type_2<other_action<subscript_action>, const std::basic_string<Char, Traits, Allocator>, B> {
933  typedef typename std::basic_string<Char, Traits, Allocator>::const_reference type;
934};
935
936
937} // namespace lambda
938} // namespace boost
939
940#endif
941
942
Note: See TracBrowser for help on using the repository browser.