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