| // Copyright Daniel Wallin, David Abrahams 2005. Use, modification and |
| // distribution is subject to the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP |
| # define BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP |
| |
| # include <boost/parameter/aux_/void.hpp> |
| # include <boost/parameter/aux_/arg_list.hpp> |
| # include <boost/parameter/aux_/result_of0.hpp> |
| # include <boost/mpl/if.hpp> |
| # include <boost/mpl/apply_wrap.hpp> |
| # include <boost/mpl/and.hpp> |
| # include <boost/mpl/not.hpp> |
| # include <boost/type_traits/is_same.hpp> |
| # include <boost/type_traits/is_convertible.hpp> |
| # include <boost/type_traits/is_reference.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| struct empty_arg_list; |
| struct arg_list_tag; |
| |
| struct tagged_argument_base {}; |
| |
| // Holds a reference to an argument of type Arg associated with |
| // keyword Keyword |
| |
| template <class Keyword, class Arg> |
| struct tagged_argument : tagged_argument_base |
| { |
| typedef Keyword key_type; |
| typedef Arg value_type; |
| typedef Arg& reference; |
| |
| tagged_argument(reference x) : value(x) {} |
| |
| // A metafunction class that, given a keyword and a default |
| // type, returns the appropriate result type for a keyword |
| // lookup given that default |
| struct binding |
| { |
| template <class KW, class Default, class Reference> |
| struct apply |
| { |
| typedef typename mpl::eval_if< |
| boost::is_same<KW, key_type> |
| , mpl::if_<Reference, reference, value_type> |
| , mpl::identity<Default> |
| >::type type; |
| }; |
| }; |
| |
| // Comma operator to compose argument list without using parameters<>. |
| // Useful for argument lists with undetermined length. |
| template <class Keyword2, class Arg2> |
| arg_list< |
| tagged_argument<Keyword, Arg> |
| , arg_list<tagged_argument<Keyword2, Arg2> > |
| > |
| operator,(tagged_argument<Keyword2, Arg2> x) const |
| { |
| return arg_list< |
| tagged_argument<Keyword, Arg> |
| , arg_list<tagged_argument<Keyword2, Arg2> > |
| >( |
| *this |
| , arg_list<tagged_argument<Keyword2, Arg2> >(x, empty_arg_list()) |
| ); |
| } |
| |
| reference operator[](keyword<Keyword> const&) const |
| { |
| return value; |
| } |
| |
| # if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
| template <class KW, class Default> |
| Default& get_with_default(default_<KW,Default> const& x, int) const |
| { |
| return x.value; |
| } |
| |
| template <class Default> |
| reference get_with_default(default_<key_type,Default> const&, long) const |
| { |
| return value; |
| } |
| |
| template <class KW, class Default> |
| typename mpl::apply_wrap3<binding, KW, Default&, mpl::true_>::type |
| operator[](default_<KW,Default> const& x) const |
| { |
| return get_with_default(x, 0L); |
| } |
| |
| template <class KW, class F> |
| typename result_of0<F>::type |
| get_with_lazy_default(lazy_default<KW,F> const& x, int) const |
| { |
| return x.compute_default(); |
| } |
| |
| template <class F> |
| reference get_with_lazy_default(lazy_default<key_type,F> const&, long) const |
| { |
| return value; |
| } |
| |
| template <class KW, class F> |
| typename mpl::apply_wrap3< |
| binding,KW |
| , typename result_of0<F>::type |
| , mpl::true_ |
| >::type |
| operator[](lazy_default<KW,F> const& x) const |
| { |
| return get_with_lazy_default(x, 0L); |
| } |
| # else |
| template <class Default> |
| reference operator[](default_<key_type,Default> const& x) const |
| { |
| return value; |
| } |
| |
| template <class F> |
| reference operator[](lazy_default<key_type,F> const& x) const |
| { |
| return value; |
| } |
| |
| template <class KW, class Default> |
| Default& operator[](default_<KW,Default> const& x) const |
| { |
| return x.value; |
| } |
| |
| template <class KW, class F> |
| typename result_of0<F>::type operator[](lazy_default<KW,F> const& x) const |
| { |
| return x.compute_default(); |
| } |
| |
| template <class ParameterRequirements> |
| static typename ParameterRequirements::has_default |
| satisfies(ParameterRequirements*); |
| |
| template <class HasDefault, class Predicate> |
| static typename mpl::apply1<Predicate, value_type>::type |
| satisfies( |
| parameter_requirements<key_type,Predicate,HasDefault>* |
| ); |
| # endif |
| |
| reference value; |
| # if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) |
| // warning suppression |
| private: |
| void operator=(tagged_argument const&); |
| public: |
| # endif |
| // MPL sequence support |
| typedef tagged_argument type; // Convenience for users |
| typedef empty_arg_list tail_type; // For the benefit of iterators |
| typedef arg_list_tag tag; // For dispatching to sequence intrinsics |
| }; |
| |
| // Defines a metafunction, is_tagged_argument, that identifies |
| // tagged_argument specializations and their derived classes. |
| template <class T> |
| struct is_tagged_argument_aux |
| : is_convertible<T*,tagged_argument_base const*> |
| {}; |
| |
| template <class T> |
| struct is_tagged_argument |
| : mpl::and_< |
| mpl::not_<is_reference<T> > |
| , is_tagged_argument_aux<T> |
| > |
| {}; |
| |
| }}} // namespace boost::parameter::aux |
| |
| #endif // BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP |
| |