Compare commits

...

3 Commits

Author SHA1 Message Date
Daniel Wallin
0071292388 unnamed parameters test
[SVN r29303]
2005-05-30 18:42:00 +00:00
Daniel Wallin
d3677ce156 unnamed parameter support & sfinae support for vc7.1
[SVN r29302]
2005-05-30 18:40:17 +00:00
nobody
73afdad1e5 This commit was manufactured by cvs2svn to create branch
'parameter-post-1_33'.

[SVN r28977]
2005-05-16 19:01:43 +00:00
6 changed files with 269 additions and 58 deletions

View File

@@ -1,14 +0,0 @@
// Copyright David Abrahams, Daniel Wallin 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_050401_HPP
#define BOOST_PARAMETER_050401_HPP
#include <boost/parameter/parameters.hpp>
#include <boost/parameter/keyword.hpp>
#include <boost/parameter/binding.hpp>
#endif // BOOST_PARAMETER_050401_HPP

View File

@@ -40,7 +40,7 @@
#define BOOST_PARAMETER_open_list(z, n, text) \
aux::make_arg_list< \
BOOST_PP_CAT(PS, n), BOOST_PP_CAT(A, n) \
BOOST_PP_CAT(PS, n), BOOST_PP_CAT(A, n), unnamed_specs \
#define BOOST_PARAMETER_close_list(z, n, text) >

View File

@@ -15,10 +15,11 @@ namespace boost { namespace parameter { namespace aux {
template <class Keyword, class Predicate, class HasDefault>
struct parameter_requirements
{
typedef Keyword keyword;
typedef Predicate predicate;
typedef HasDefault has_default;
};
}}} // namespace boost::parameter::aux
#endif // PARAMETER_REQUIREMENTS_050331_HPP

View File

@@ -15,7 +15,9 @@
#include <boost/mpl/identity.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/iterator/detail/config_def.hpp>
#include <boost/python/detail/is_xxx.hpp>
@@ -76,18 +78,21 @@ struct optional
typedef Predicate predicate;
};
template <class Tag>
template <class Tag, class Predicate>
struct unnamed
{
typedef Tag key_type;
typedef Predicate predicate;
};
namespace aux
{
// Defines metafunctions, is_required and is_optional, that
// identify required<...> and optional<...> specializations.
namespace aux {
// Defines metafunctions, is_required, is_optional and is_unnamed,
// that identify required<...>, optional<...> and unnamed<>
// specializations.
BOOST_PYTHON_IS_XXX_DEF(required, required, 2)
BOOST_PYTHON_IS_XXX_DEF(optional, optional, 2)
BOOST_PYTHON_IS_XXX_DEF(unnamed, unnamed, 2)
//
// key_type, has_default, and predicate --
@@ -100,11 +105,16 @@ namespace aux
// a ParameterSpec is a specialization of either keyword<...>,
// required<...> or optional<...>.
//
// helper for key_type<...>, below.
template <class T>
struct get_key_type
{ typedef typename T::key_type type; };
: mpl::if_<
is_unnamed<typename T::key_type>
, get_key_type<typename T::key_type>
, mpl::identity<typename T::key_type>
>::type
{};
template <class T>
struct key_type
@@ -112,6 +122,7 @@ namespace aux
mpl::or_<
is_optional<T>
, is_required<T>
, is_unnamed<T>
>
, get_key_type<T>
, mpl::identity<T>
@@ -141,11 +152,12 @@ namespace aux
// helper for predicate<...>, below
template <class T>
struct get_predicate
{
typedef typename
get_predicate_or_default<typename T::predicate>::type
type;
};
: mpl::if_<
is_unnamed<typename T::key_type>
, get_predicate<typename T::key_type>
, get_predicate_or_default<typename T::predicate>
>::type
{};
template <class T>
struct predicate
@@ -153,6 +165,7 @@ namespace aux
mpl::or_<
is_optional<T>
, is_required<T>
, is_unnamed<T>
>
, get_predicate<T>
, mpl::identity<mpl::always<mpl::true_> >
@@ -175,24 +188,21 @@ namespace aux
> type;
};
// Labels Arg with default keyword tag DefaultTag if it is not
// already a tagged_argument
template <class DefaultTag, class Arg>
// Labels Arg with default keyword tag from ParameterSpec
// if it is not already a tagged_argument
template <class ParameterSpec, class Arg, class Unnamed>
struct as_tagged_argument
{
typedef typename mpl::if_<
typedef typename mpl::eval_if<
is_tagged_argument<Arg>
, Arg
, tagged_argument<
typename key_type<DefaultTag>::type
, typename unwrap_cv_reference<Arg const>::type
>
, mpl::identity<Arg>
, mpl::apply_wrap2<Unnamed, Arg, typename key_type<ParameterSpec>::type>
>::type type;
};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround
template <>
struct as_tagged_argument<int,int>
struct as_tagged_argument<int,int,int>
{
typedef int type;
};
@@ -203,6 +213,24 @@ namespace aux
template <class ArgList, class ParameterRequirements>
struct satisfies
{
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
// VC7.1 can't handle the sizeof() implementation below,
// so we use this instead.
typedef typename mpl::apply_wrap2<
typename ArgList::binding
, typename ParameterRequirements::keyword
, void_
>::type bound;
typedef typename mpl::eval_if<
is_same<bound, void_>
, typename ParameterRequirements::has_default
, mpl::apply1<
typename ParameterRequirements::predicate
, typename remove_reference<bound>::type
>
>::type type;
#else
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(
@@ -214,6 +242,7 @@ namespace aux
);
typedef mpl::bool_<satisfies::value> type;
#endif
};
// Returns mpl::true_ if the requirements of the given ParameterSpec
@@ -229,11 +258,11 @@ namespace aux
// Helper for make_partial_arg_list, below. Produce an arg_list
// node for the given ParameterSpec and ArgumentType, whose tail is
// determined by invoking the nullary metafunction TailFn.
template <class ParameterSpec, class ArgumentType, class TailFn>
template <class ParameterSpec, class ArgumentType, class Unnamed, class TailFn>
struct make_arg_list
{
typedef arg_list<
typename as_tagged_argument<ParameterSpec,ArgumentType>::type
typename as_tagged_argument<ParameterSpec,ArgumentType,Unnamed>::type
, typename TailFn::type
> type;
};
@@ -245,13 +274,14 @@ namespace aux
template <
class ParameterSpec
, class ArgumentType
, class Unnamed
, class TailFn
>
struct make_partial_arg_list
: mpl::eval_if<
is_same<ArgumentType,void_>
, mpl::identity<empty_arg_list>
, make_arg_list<ParameterSpec, ArgumentType, TailFn>
, make_arg_list<ParameterSpec, ArgumentType, Unnamed, TailFn>
>
{};
@@ -267,14 +297,127 @@ namespace aux
#define BOOST_PARAMETER_make_arg_list(z, n, names) \
BOOST_PP_SEQ_ELEM(0,names)< \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n), \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n),
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,names), n), \
BOOST_PP_SEQ_ELEM(3,names),
#define BOOST_PARAMETER_right_angle(z, n, text) >
#define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type) \
#define BOOST_PARAMETER_build_arg_list(n, make, parameter_spec, argument_type, unnamed) \
BOOST_PP_REPEAT( \
n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)(unnamed)) \
mpl::identity<aux::empty_arg_list> \
BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
// Metafunctions used to determine if a ParameterSpec is
// either unnamed<something, something> or
// [required/optional]<unnamed<something, something> >
template <class T>
struct is_nested_unnamed_aux
: is_unnamed<typename T::key_type>
{};
template <class T>
struct is_nested_unnamed
: mpl::if_<
mpl::or_<
is_optional<T>
, is_required<T>
>
, is_nested_unnamed_aux<T>
, mpl::false_
>::type
{};
template <class T>
struct is_unnamed_spec
: mpl::or_<
is_unnamed<T>
, is_nested_unnamed<T>
>
{};
// List of unnamed keywords with the associated predicate.
template <class Keyword, class Predicate, class Tail>
struct unnamed_list
{
// If the Predicate applies; tag the argument with
// Keyword. Otherwise, try the tail.
template <class Arg, class DefaultTag>
struct apply
{
typedef typename mpl::eval_if<
typename mpl::apply1<Predicate, Arg>::type
, mpl::identity<tagged_argument<
Keyword
, typename unwrap_cv_reference<Arg const>::type
> >
, mpl::apply_wrap2<Tail, Arg, DefaultTag>
>::type type;
};
};
// Terminates an unnamed_list<>.
struct empty_unnamed_list
{
// Default case. No unnamed predicates matched the Arg.
// Tag argument with the DefaultTag.
template <class Arg, class DefaultTag>
struct apply
{
typedef tagged_argument<
DefaultTag
, typename unwrap_cv_reference<Arg const>::type
> type;
};
};
template <class ParameterSpec, class TailFn>
struct make_unnamed_list_aux
{
typedef typename mpl::if_<
is_unnamed_spec<ParameterSpec>
, unnamed_list<
typename key_type<ParameterSpec>::type
, typename predicate<ParameterSpec>::type
, typename TailFn::type
>
, typename TailFn::type
>::type type;
};
template <class ParameterSpec, class TailFn>
struct make_unnamed_list
{
typedef typename mpl::eval_if<
is_same<ParameterSpec, void_>
, mpl::identity<empty_unnamed_list>
, make_unnamed_list_aux<ParameterSpec, TailFn>
>::type type;
};
// Generates:
//
// make<
// parameter_spec#0
// , make<
// parameter_spec#1
// , make<
// parameter_spec#2
// , mpl::identity<mpl::vector0<> >
// >
// >
// >
//
#define BOOST_PARAMETER_make_unnamed_list(z, n, names) \
BOOST_PP_SEQ_ELEM(0,names)< \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(1,names), n),
#define BOOST_PARAMETER_build_unnamed_list(n, make, parameter_spec) \
BOOST_PP_REPEAT( \
n, BOOST_PARAMETER_make_arg_list, (make)(parameter_spec)(argument_type)) \
mpl::identity<aux::empty_arg_list> \
n, BOOST_PARAMETER_make_unnamed_list, (make)(parameter_spec)) \
mpl::identity<aux::empty_unnamed_list> \
BOOST_PP_REPEAT(n, BOOST_PARAMETER_right_angle, _)
} // namespace aux
@@ -289,6 +432,12 @@ struct parameters
{
#undef BOOST_PARAMETER_TEMPLATE_ARGS
typedef typename BOOST_PARAMETER_build_unnamed_list(
BOOST_PARAMETER_MAX_ARITY
, aux::make_unnamed_list
, PS
)::type unnamed_specs;
// if the elements of NamedList match the criteria of overload
// resolution, returns a type which can be constructed from
// parameters. Otherwise, this is not a valid metafunction (no nested
@@ -319,12 +468,15 @@ struct parameters
# undef BOOST_PARAMETER_satisfies
, mpl::identity<parameters>
, mpl::identity<
parameters<BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)>
>
, aux::void_
>
{};
{
};
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
@@ -333,13 +485,13 @@ struct parameters
template<
BOOST_PP_ENUM_BINARY_PARAMS(
BOOST_PARAMETER_MAX_ARITY, class A, = aux::void_ BOOST_PP_INTERCEPT
)
)
>
struct restrict
# ifndef BOOST_NO_SFINAE
: restrict_base<
typename BOOST_PARAMETER_build_arg_list(
BOOST_PARAMETER_MAX_ARITY, aux::make_partial_arg_list, PS, A
BOOST_PARAMETER_MAX_ARITY, aux::make_partial_arg_list, PS, A, unnamed_specs
)::type
>::type
{};
@@ -365,12 +517,12 @@ struct parameters
template<class A0>
typename
aux::make_arg_list<PS0,A0, mpl::identity<aux::empty_arg_list> >
aux::make_arg_list<PS0,A0,unnamed_specs, mpl::identity<aux::empty_arg_list> >
::type
operator()( A0 const& a0) const
{
typedef typename
aux::make_arg_list<PS0, A0, mpl::identity<aux::empty_arg_list> >
aux::make_arg_list<PS0, A0, unnamed_specs, mpl::identity<aux::empty_arg_list> >
::type result_type;
return result_type(
@@ -385,9 +537,9 @@ struct parameters
template<class A0, class A1>
typename
aux::make_arg_list<
PS0,A0
PS0,A0,unnamed_specs
, aux::make_arg_list<
PS1,A1
PS1,A1,unnamed_specs
, mpl::identity<aux::empty_arg_list>
>
>
@@ -396,9 +548,9 @@ struct parameters
{
typedef typename
aux::make_arg_list<
PS0,A0
PS0,A0,unnamed_specs
, aux::make_arg_list<
PS1,A1
PS1,A1,unnamed_specs
, mpl::identity<aux::empty_arg_list>
>
>

View File

@@ -10,6 +10,7 @@ import testing ;
: [ run basics.cpp ]
[ run sfinae.cpp ]
[ run macros.cpp ]
[ run unnamed.cpp ]
;
}

71
test/unnamed.cpp Executable file
View File

@@ -0,0 +1,71 @@
// Copyright David Abrahams, Daniel Wallin 2003. 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)
#include <boost/parameter.hpp>
#include <cassert>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <string>
namespace test
{
using namespace boost::parameter;
namespace mpl = boost::mpl;
struct g_parameters
: parameters<
unnamed<struct name_, boost::is_convertible<mpl::_, std::string> >
, unnamed<struct value_, boost::is_convertible<mpl::_, float> >
>
{};
keyword<struct name_> name;
keyword<struct value_> value;
template<class Params>
int g_(Params const& p)
{
assert(p[name] == std::string("foo"));
assert(p[value] == 3.14f);
return 1;
}
template<class A0>
int g(A0 const& a0)
{
return g_(g_parameters()(a0));
}
template<class A0, class A1>
int g(A0 const& a0, A1 const& a1)
{
return g_(g_parameters()(a0, a1));
}
}
#include <typeinfo>
#include <iostream>
int main()
{
using test::g;
using test::name;
using test::value;
g("foo", 3.14f);
g(3.14f, "foo");
g(value = 3.14f, "foo");
g(name = "foo", 3.14f);
g(3.14f, name = "foo");
g(name = "foo", value = 3.14f);
// g((void*)0, (void*)0);
return 0;
}