1 // (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
2 // sell and distribute this software is granted provided this
3 // copyright notice appears in all copies. This software is provided
4 // "as is" without express or implied warranty, and with no claim as
5 // to its suitability for any purpose.
9 // 04 Oct 2001 David Abrahams
10 // Changed name of "bind" to "select" to avoid problems with MSVC.
12 #ifndef BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP
13 #define BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP
15 #include <boost/type_traits/conversion_traits.hpp>
16 #include <boost/type_traits/composite_traits.hpp> // for is_reference
17 #if defined(__BORLANDC__)
18 #include <boost/type_traits/ice.hpp>
24 struct default_argument { };
26 struct dummy_default_gen {
27 template <class Base, class Traits>
29 typedef default_argument type;
33 // This class template is a workaround for MSVC.
34 template <class Gen> struct default_generator {
35 typedef detail::dummy_default_gen type;
38 template <class T> struct is_default {
39 enum { value = false };
40 typedef type_traits::no_type type;
42 template <> struct is_default<default_argument> {
43 enum { value = true };
44 typedef type_traits::yes_type type;
47 struct choose_default {
48 template <class Arg, class DefaultGen, class Base, class Traits>
50 typedef typename default_generator<DefaultGen>::type Gen;
51 typedef typename Gen::template select<Base,Traits>::type type;
55 template <class Arg, class DefaultGen, class Base, class Traits>
61 #if defined(__BORLANDC__)
62 template <class UseDefault>
63 struct choose_arg_or_default { typedef choose_arg type; };
65 struct choose_arg_or_default<type_traits::yes_type> {
66 typedef choose_default type;
69 template <bool UseDefault>
70 struct choose_arg_or_default { typedef choose_arg type; };
72 struct choose_arg_or_default<true> {
73 typedef choose_default type;
77 template <class Arg, class DefaultGen, class Base, class Traits>
78 class resolve_default {
79 #if defined(__BORLANDC__)
80 typedef typename choose_arg_or_default<typename is_default<Arg>::type>::type Selector;
82 // This usually works for Borland, but I'm seeing weird errors in
83 // iterator_adaptor_test.cpp when using this method.
84 enum { is_def = is_default<Arg>::value };
85 typedef typename choose_arg_or_default<is_def>::type Selector;
88 typedef typename Selector
89 ::template select<Arg, DefaultGen, Base, Traits>::type type;
92 // To differentiate an unnamed parameter from a traits generator
93 // we use is_convertible<X, iter_traits_gen_base>.
94 struct named_template_param_base { };
97 struct is_named_param_list {
98 enum { value = is_convertible<X, named_template_param_base>::value };
101 struct choose_named_params {
102 template <class Prev> struct select { typedef Prev type; };
104 struct choose_default_arg {
105 template <class Prev> struct select {
106 typedef detail::default_argument type;
110 template <bool Named> struct choose_default_dispatch_;
111 template <> struct choose_default_dispatch_<true> {
112 typedef choose_named_params type;
114 template <> struct choose_default_dispatch_<false> {
115 typedef choose_default_arg type;
117 // The use of inheritance here is a Solaris Forte 6 workaround.
118 template <bool Named> struct choose_default_dispatch
119 : public choose_default_dispatch_<Named> { };
121 template <class PreviousArg>
122 struct choose_default_argument {
123 enum { is_named = is_named_param_list<PreviousArg>::value };
124 typedef typename choose_default_dispatch<is_named>::type Selector;
125 typedef typename Selector::template select<PreviousArg>::type type;
128 // This macro assumes that there is a class named default_##TYPE
129 // defined before the application of the macro. This class should
130 // have a single member class template named "select" with two
131 // template parameters: the type of the class being created (e.g.,
132 // the iterator_adaptor type when creating iterator adaptors) and
133 // a traits class. The select class should have a single typedef
134 // named "type" that produces the default for TYPE. See
135 // boost/iterator_adaptors.hpp for an example usage. Also,
136 // applications of this macro must be placed in namespace
139 #define BOOST_NAMED_TEMPLATE_PARAM(TYPE) \
140 struct get_##TYPE##_from_named { \
141 template <class Base, class NamedParams, class Traits> \
143 typedef typename NamedParams::traits NamedTraits; \
144 typedef typename NamedTraits::TYPE TYPE; \
145 typedef typename resolve_default<TYPE, \
146 default_##TYPE, Base, NamedTraits>::type type; \
149 struct pass_thru_##TYPE { \
150 template <class Base, class Arg, class Traits> struct select { \
151 typedef typename resolve_default<Arg, \
152 default_##TYPE, Base, Traits>::type type; \
155 template <int NamedParam> \
156 struct get_##TYPE##_dispatch { }; \
157 template <> struct get_##TYPE##_dispatch<1> { \
158 typedef get_##TYPE##_from_named type; \
160 template <> struct get_##TYPE##_dispatch<0> { \
161 typedef pass_thru_##TYPE type; \
163 template <class Base, class X, class Traits> \
165 enum { is_named = is_named_param_list<X>::value }; \
166 typedef typename get_##TYPE##_dispatch<is_named>::type Selector; \
168 typedef typename Selector::template select<Base, X, Traits>::type type; \
170 template <> struct default_generator<default_##TYPE> { \
171 typedef default_##TYPE type; \
175 } // namespace detail
178 #endif // BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP