1 // (C) Copyright Jeremy Siek 2001.
\r
2 // Distributed under the Boost Software License, Version 1.0. (See
\r
3 // accompanying file LICENSE_1_0.txt or copy at
\r
4 // http://www.boost.org/LICENSE_1_0.txt)
\r
8 // 04 Oct 2001 David Abrahams
\r
9 // Changed name of "bind" to "select" to avoid problems with MSVC.
\r
11 #ifndef BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP
\r
12 #define BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP
\r
14 #include <boost/type_traits/conversion_traits.hpp>
\r
15 #include <boost/type_traits/composite_traits.hpp> // for is_reference
\r
16 #if defined(__BORLANDC__)
\r
17 #include <boost/type_traits/ice.hpp>
\r
23 struct default_argument { };
\r
25 struct dummy_default_gen {
\r
26 template <class Base, class Traits>
\r
28 typedef default_argument type;
\r
32 // This class template is a workaround for MSVC.
\r
33 template <class Gen> struct default_generator {
\r
34 typedef detail::dummy_default_gen type;
\r
37 template <class T> struct is_default {
\r
38 enum { value = false };
\r
39 typedef type_traits::no_type type;
\r
41 template <> struct is_default<default_argument> {
\r
42 enum { value = true };
\r
43 typedef type_traits::yes_type type;
\r
46 struct choose_default {
\r
47 template <class Arg, class DefaultGen, class Base, class Traits>
\r
49 typedef typename default_generator<DefaultGen>::type Gen;
\r
50 typedef typename Gen::template select<Base,Traits>::type type;
\r
54 template <class Arg, class DefaultGen, class Base, class Traits>
\r
60 #if defined(__BORLANDC__)
\r
61 template <class UseDefault>
\r
62 struct choose_arg_or_default { typedef choose_arg type; };
\r
64 struct choose_arg_or_default<type_traits::yes_type> {
\r
65 typedef choose_default type;
\r
68 template <bool UseDefault>
\r
69 struct choose_arg_or_default { typedef choose_arg type; };
\r
71 struct choose_arg_or_default<true> {
\r
72 typedef choose_default type;
\r
76 template <class Arg, class DefaultGen, class Base, class Traits>
\r
77 class resolve_default {
\r
78 #if defined(__BORLANDC__)
\r
79 typedef typename choose_arg_or_default<typename is_default<Arg>::type>::type Selector;
\r
81 // This usually works for Borland, but I'm seeing weird errors in
\r
82 // iterator_adaptor_test.cpp when using this method.
\r
83 enum { is_def = is_default<Arg>::value };
\r
84 typedef typename choose_arg_or_default<is_def>::type Selector;
\r
87 typedef typename Selector
\r
88 ::template select<Arg, DefaultGen, Base, Traits>::type type;
\r
91 // To differentiate an unnamed parameter from a traits generator
\r
92 // we use is_convertible<X, iter_traits_gen_base>.
\r
93 struct named_template_param_base { };
\r
96 struct is_named_param_list {
\r
97 enum { value = is_convertible<X, named_template_param_base>::value };
\r
100 struct choose_named_params {
\r
101 template <class Prev> struct select { typedef Prev type; };
\r
103 struct choose_default_arg {
\r
104 template <class Prev> struct select {
\r
105 typedef detail::default_argument type;
\r
109 template <bool Named> struct choose_default_dispatch_;
\r
110 template <> struct choose_default_dispatch_<true> {
\r
111 typedef choose_named_params type;
\r
113 template <> struct choose_default_dispatch_<false> {
\r
114 typedef choose_default_arg type;
\r
116 // The use of inheritance here is a Solaris Forte 6 workaround.
\r
117 template <bool Named> struct choose_default_dispatch
\r
118 : public choose_default_dispatch_<Named> { };
\r
120 template <class PreviousArg>
\r
121 struct choose_default_argument {
\r
122 enum { is_named = is_named_param_list<PreviousArg>::value };
\r
123 typedef typename choose_default_dispatch<is_named>::type Selector;
\r
124 typedef typename Selector::template select<PreviousArg>::type type;
\r
127 // This macro assumes that there is a class named default_##TYPE
\r
128 // defined before the application of the macro. This class should
\r
129 // have a single member class template named "select" with two
\r
130 // template parameters: the type of the class being created (e.g.,
\r
131 // the iterator_adaptor type when creating iterator adaptors) and
\r
132 // a traits class. The select class should have a single typedef
\r
133 // named "type" that produces the default for TYPE. See
\r
134 // boost/iterator_adaptors.hpp for an example usage. Also,
\r
135 // applications of this macro must be placed in namespace
\r
138 #define BOOST_NAMED_TEMPLATE_PARAM(TYPE) \
\r
139 struct get_##TYPE##_from_named { \
\r
140 template <class Base, class NamedParams, class Traits> \
\r
142 typedef typename NamedParams::traits NamedTraits; \
\r
143 typedef typename NamedTraits::TYPE TYPE; \
\r
144 typedef typename resolve_default<TYPE, \
\r
145 default_##TYPE, Base, NamedTraits>::type type; \
\r
148 struct pass_thru_##TYPE { \
\r
149 template <class Base, class Arg, class Traits> struct select { \
\r
150 typedef typename resolve_default<Arg, \
\r
151 default_##TYPE, Base, Traits>::type type; \
\r
154 template <int NamedParam> \
\r
155 struct get_##TYPE##_dispatch { }; \
\r
156 template <> struct get_##TYPE##_dispatch<1> { \
\r
157 typedef get_##TYPE##_from_named type; \
\r
159 template <> struct get_##TYPE##_dispatch<0> { \
\r
160 typedef pass_thru_##TYPE type; \
\r
162 template <class Base, class X, class Traits> \
\r
163 class get_##TYPE { \
\r
164 enum { is_named = is_named_param_list<X>::value }; \
\r
165 typedef typename get_##TYPE##_dispatch<is_named>::type Selector; \
\r
167 typedef typename Selector::template select<Base, X, Traits>::type type; \
\r
169 template <> struct default_generator<default_##TYPE> { \
\r
170 typedef default_##TYPE type; \
\r
174 } // namespace detail
\r
175 } // namespace boost
\r
177 #endif // BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP
\r