Chris@16: // (C) Copyright Jeremy Siek 2001. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Revision History: Chris@16: Chris@16: // 04 Oct 2001 David Abrahams Chris@16: // Changed name of "bind" to "select" to avoid problems with MSVC. Chris@16: Chris@16: #ifndef BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP Chris@16: #define BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP Chris@16: Chris@16: #include Chris@16: #include // for is_reference Chris@16: #if defined(__BORLANDC__) Chris@16: #include Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace detail { Chris@16: Chris@16: struct default_argument { }; Chris@16: Chris@16: struct dummy_default_gen { Chris@16: template Chris@16: struct select { Chris@16: typedef default_argument type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: // This class template is a workaround for MSVC. Chris@16: template struct default_generator { Chris@16: typedef detail::dummy_default_gen type; Chris@16: }; Chris@16: Chris@16: template struct is_default { Chris@16: enum { value = false }; Chris@16: typedef type_traits::no_type type; Chris@16: }; Chris@16: template <> struct is_default { Chris@16: enum { value = true }; Chris@16: typedef type_traits::yes_type type; Chris@16: }; Chris@16: Chris@16: struct choose_default { Chris@16: template Chris@16: struct select { Chris@16: typedef typename default_generator::type Gen; Chris@16: typedef typename Gen::template select::type type; Chris@16: }; Chris@16: }; Chris@16: struct choose_arg { Chris@16: template Chris@16: struct select { Chris@16: typedef Arg type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: #if defined(__BORLANDC__) Chris@16: template Chris@16: struct choose_arg_or_default { typedef choose_arg type; }; Chris@16: template <> Chris@16: struct choose_arg_or_default { Chris@16: typedef choose_default type; Chris@16: }; Chris@16: #else Chris@16: template Chris@16: struct choose_arg_or_default { typedef choose_arg type; }; Chris@16: template <> Chris@16: struct choose_arg_or_default { Chris@16: typedef choose_default type; Chris@16: }; Chris@16: #endif Chris@16: Chris@16: template Chris@16: class resolve_default { Chris@16: #if defined(__BORLANDC__) Chris@16: typedef typename choose_arg_or_default::type>::type Selector; Chris@16: #else Chris@16: // This usually works for Borland, but I'm seeing weird errors in Chris@16: // iterator_adaptor_test.cpp when using this method. Chris@16: enum { is_def = is_default::value }; Chris@16: typedef typename choose_arg_or_default::type Selector; Chris@16: #endif Chris@16: public: Chris@16: typedef typename Selector Chris@16: ::template select::type type; Chris@16: }; Chris@16: Chris@16: // To differentiate an unnamed parameter from a traits generator Chris@16: // we use is_convertible. Chris@16: struct named_template_param_base { }; Chris@16: Chris@16: template Chris@16: struct is_named_param_list { Chris@16: enum { value = is_convertible::value }; Chris@16: }; Chris@16: Chris@16: struct choose_named_params { Chris@16: template struct select { typedef Prev type; }; Chris@16: }; Chris@16: struct choose_default_arg { Chris@16: template struct select { Chris@16: typedef detail::default_argument type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template struct choose_default_dispatch_; Chris@16: template <> struct choose_default_dispatch_ { Chris@16: typedef choose_named_params type; Chris@16: }; Chris@16: template <> struct choose_default_dispatch_ { Chris@16: typedef choose_default_arg type; Chris@16: }; Chris@16: // The use of inheritance here is a Solaris Forte 6 workaround. Chris@16: template struct choose_default_dispatch Chris@16: : public choose_default_dispatch_ { }; Chris@16: Chris@16: template Chris@16: struct choose_default_argument { Chris@16: enum { is_named = is_named_param_list::value }; Chris@16: typedef typename choose_default_dispatch::type Selector; Chris@16: typedef typename Selector::template select::type type; Chris@16: }; Chris@16: Chris@16: // This macro assumes that there is a class named default_##TYPE Chris@16: // defined before the application of the macro. This class should Chris@16: // have a single member class template named "select" with two Chris@16: // template parameters: the type of the class being created (e.g., Chris@16: // the iterator_adaptor type when creating iterator adaptors) and Chris@16: // a traits class. The select class should have a single typedef Chris@16: // named "type" that produces the default for TYPE. See Chris@16: // boost/iterator_adaptors.hpp for an example usage. Also, Chris@16: // applications of this macro must be placed in namespace Chris@16: // boost::detail. Chris@16: Chris@16: #define BOOST_NAMED_TEMPLATE_PARAM(TYPE) \ Chris@16: struct get_##TYPE##_from_named { \ Chris@16: template \ Chris@16: struct select { \ Chris@16: typedef typename NamedParams::traits NamedTraits; \ Chris@16: typedef typename NamedTraits::TYPE TYPE; \ Chris@16: typedef typename resolve_default::type type; \ Chris@16: }; \ Chris@16: }; \ Chris@16: struct pass_thru_##TYPE { \ Chris@16: template struct select { \ Chris@16: typedef typename resolve_default::type type; \ Chris@16: };\ Chris@16: }; \ Chris@16: template \ Chris@16: struct get_##TYPE##_dispatch { }; \ Chris@16: template <> struct get_##TYPE##_dispatch<1> { \ Chris@16: typedef get_##TYPE##_from_named type; \ Chris@16: }; \ Chris@16: template <> struct get_##TYPE##_dispatch<0> { \ Chris@16: typedef pass_thru_##TYPE type; \ Chris@16: }; \ Chris@16: template \ Chris@16: class get_##TYPE { \ Chris@16: enum { is_named = is_named_param_list::value }; \ Chris@16: typedef typename get_##TYPE##_dispatch::type Selector; \ Chris@16: public: \ Chris@16: typedef typename Selector::template select::type type; \ Chris@16: }; \ Chris@16: template <> struct default_generator { \ Chris@16: typedef default_##TYPE type; \ Chris@16: } Chris@16: Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP