]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright Jeremy Siek 2001. |
2 | // Distributed under the Boost Software License, Version 1.0. (See | |
3 | // accompanying file LICENSE_1_0.txt or copy at | |
4 | // http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // Revision History: | |
7 | ||
8 | // 04 Oct 2001 David Abrahams | |
9 | // Changed name of "bind" to "select" to avoid problems with MSVC. | |
10 | ||
11 | #ifndef BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP | |
12 | #define BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP | |
13 | ||
14 | #include <boost/type_traits/conversion_traits.hpp> | |
15 | #include <boost/type_traits/composite_traits.hpp> // for is_reference | |
16 | #if defined(__BORLANDC__) | |
17 | #include <boost/type_traits/ice.hpp> | |
18 | #endif | |
19 | ||
20 | namespace boost { | |
21 | namespace detail { | |
22 | ||
23 | struct default_argument { }; | |
24 | ||
25 | struct dummy_default_gen { | |
26 | template <class Base, class Traits> | |
27 | struct select { | |
28 | typedef default_argument type; | |
29 | }; | |
30 | }; | |
31 | ||
32 | // This class template is a workaround for MSVC. | |
33 | template <class Gen> struct default_generator { | |
34 | typedef detail::dummy_default_gen type; | |
35 | }; | |
36 | ||
37 | template <class T> struct is_default { | |
38 | enum { value = false }; | |
39 | typedef type_traits::no_type type; | |
40 | }; | |
41 | template <> struct is_default<default_argument> { | |
42 | enum { value = true }; | |
43 | typedef type_traits::yes_type type; | |
44 | }; | |
45 | ||
46 | struct choose_default { | |
47 | template <class Arg, class DefaultGen, class Base, class Traits> | |
48 | struct select { | |
49 | typedef typename default_generator<DefaultGen>::type Gen; | |
50 | typedef typename Gen::template select<Base,Traits>::type type; | |
51 | }; | |
52 | }; | |
53 | struct choose_arg { | |
54 | template <class Arg, class DefaultGen, class Base, class Traits> | |
55 | struct select { | |
56 | typedef Arg type; | |
57 | }; | |
58 | }; | |
59 | ||
60 | #if defined(__BORLANDC__) | |
61 | template <class UseDefault> | |
62 | struct choose_arg_or_default { typedef choose_arg type; }; | |
63 | template <> | |
64 | struct choose_arg_or_default<type_traits::yes_type> { | |
65 | typedef choose_default type; | |
66 | }; | |
67 | #else | |
68 | template <bool UseDefault> | |
69 | struct choose_arg_or_default { typedef choose_arg type; }; | |
70 | template <> | |
71 | struct choose_arg_or_default<true> { | |
72 | typedef choose_default type; | |
73 | }; | |
74 | #endif | |
75 | ||
76 | template <class Arg, class DefaultGen, class Base, class Traits> | |
77 | class resolve_default { | |
78 | #if defined(__BORLANDC__) | |
79 | typedef typename choose_arg_or_default<typename is_default<Arg>::type>::type Selector; | |
80 | #else | |
81 | // This usually works for Borland, but I'm seeing weird errors in | |
82 | // iterator_adaptor_test.cpp when using this method. | |
83 | enum { is_def = is_default<Arg>::value }; | |
84 | typedef typename choose_arg_or_default<is_def>::type Selector; | |
85 | #endif | |
86 | public: | |
87 | typedef typename Selector | |
88 | ::template select<Arg, DefaultGen, Base, Traits>::type type; | |
89 | }; | |
90 | ||
91 | // To differentiate an unnamed parameter from a traits generator | |
92 | // we use is_convertible<X, iter_traits_gen_base>. | |
93 | struct named_template_param_base { }; | |
94 | ||
95 | template <class X> | |
96 | struct is_named_param_list { | |
97 | enum { value = is_convertible<X, named_template_param_base>::value }; | |
98 | }; | |
99 | ||
100 | struct choose_named_params { | |
101 | template <class Prev> struct select { typedef Prev type; }; | |
102 | }; | |
103 | struct choose_default_arg { | |
104 | template <class Prev> struct select { | |
105 | typedef detail::default_argument type; | |
106 | }; | |
107 | }; | |
108 | ||
109 | template <bool Named> struct choose_default_dispatch_; | |
110 | template <> struct choose_default_dispatch_<true> { | |
111 | typedef choose_named_params type; | |
112 | }; | |
113 | template <> struct choose_default_dispatch_<false> { | |
114 | typedef choose_default_arg type; | |
115 | }; | |
116 | // The use of inheritance here is a Solaris Forte 6 workaround. | |
117 | template <bool Named> struct choose_default_dispatch | |
118 | : public choose_default_dispatch_<Named> { }; | |
119 | ||
120 | template <class PreviousArg> | |
121 | struct choose_default_argument { | |
122 | enum { is_named = is_named_param_list<PreviousArg>::value }; | |
123 | typedef typename choose_default_dispatch<is_named>::type Selector; | |
124 | typedef typename Selector::template select<PreviousArg>::type type; | |
125 | }; | |
126 | ||
127 | // This macro assumes that there is a class named default_##TYPE | |
128 | // defined before the application of the macro. This class should | |
129 | // have a single member class template named "select" with two | |
130 | // template parameters: the type of the class being created (e.g., | |
131 | // the iterator_adaptor type when creating iterator adaptors) and | |
132 | // a traits class. The select class should have a single typedef | |
133 | // named "type" that produces the default for TYPE. See | |
134 | // boost/iterator_adaptors.hpp for an example usage. Also, | |
135 | // applications of this macro must be placed in namespace | |
136 | // boost::detail. | |
137 | ||
138 | #define BOOST_NAMED_TEMPLATE_PARAM(TYPE) \ | |
139 | struct get_##TYPE##_from_named { \ | |
140 | template <class Base, class NamedParams, class Traits> \ | |
141 | struct select { \ | |
142 | typedef typename NamedParams::traits NamedTraits; \ | |
143 | typedef typename NamedTraits::TYPE TYPE; \ | |
144 | typedef typename resolve_default<TYPE, \ | |
145 | default_##TYPE, Base, NamedTraits>::type type; \ | |
146 | }; \ | |
147 | }; \ | |
148 | struct pass_thru_##TYPE { \ | |
149 | template <class Base, class Arg, class Traits> struct select { \ | |
150 | typedef typename resolve_default<Arg, \ | |
151 | default_##TYPE, Base, Traits>::type type; \ | |
152 | };\ | |
153 | }; \ | |
154 | template <int NamedParam> \ | |
155 | struct get_##TYPE##_dispatch { }; \ | |
156 | template <> struct get_##TYPE##_dispatch<1> { \ | |
157 | typedef get_##TYPE##_from_named type; \ | |
158 | }; \ | |
159 | template <> struct get_##TYPE##_dispatch<0> { \ | |
160 | typedef pass_thru_##TYPE type; \ | |
161 | }; \ | |
162 | template <class Base, class X, class Traits> \ | |
163 | class get_##TYPE { \ | |
164 | enum { is_named = is_named_param_list<X>::value }; \ | |
165 | typedef typename get_##TYPE##_dispatch<is_named>::type Selector; \ | |
166 | public: \ | |
167 | typedef typename Selector::template select<Base, X, Traits>::type type; \ | |
168 | }; \ | |
169 | template <> struct default_generator<default_##TYPE> { \ | |
170 | typedef default_##TYPE type; \ | |
171 | } | |
172 | ||
173 | ||
174 | } // namespace detail | |
175 | } // namespace boost | |
176 | ||
177 | #endif // BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP |