diff --git a/include/boost/parameter/aux_/arg_list.hpp b/include/boost/parameter/aux_/arg_list.hpp index 2f0d135..a46483e 100755 --- a/include/boost/parameter/aux_/arg_list.hpp +++ b/include/boost/parameter/aux_/arg_list.hpp @@ -136,6 +136,7 @@ struct arg_list : Next { typedef typename TaggedArg::key_type key_type; typedef typename TaggedArg::value_type value_type; + typedef typename TaggedArg::reference reference; TaggedArg arg; // Stores the argument @@ -172,7 +173,7 @@ struct arg_list : Next { typedef typename mpl::eval_if< boost::is_same - , add_reference + , mpl::identity , mpl::apply_wrap2 >::type type; }; @@ -239,38 +240,38 @@ struct arg_list : Next // reached, indicating no matching argument was passed, the // default is returned, or if no default_ or lazy_default was // passed, compilation fails. - value_type& get(keyword x) const + reference get(keyword x) const { return arg.value; } template - value_type& get(default_ x) const + reference get(default_ x) const { return arg.value; } template - value_type& get(lazy_default x) const + reference get(lazy_default x) const { return arg.value; } #else - value_type& operator[](keyword x) const + reference operator[](keyword x) const { return arg.value; } template - value_type& operator[](default_ x) const + reference operator[](default_ x) const { return arg.value; } template - value_type& operator[](lazy_default x) const + reference operator[](lazy_default x) const { return arg.value; } diff --git a/include/boost/parameter/aux_/tag.hpp b/include/boost/parameter/aux_/tag.hpp new file mode 100755 index 0000000..a542c61 --- /dev/null +++ b/include/boost/parameter/aux_/tag.hpp @@ -0,0 +1,40 @@ +// Copyright David Abrahams 2005. Distributed under 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_AUX_TAG_DWA2005610_HPP +# define BOOST_PARAMETER_AUX_TAG_DWA2005610_HPP + +# include + +namespace boost { namespace parameter { namespace aux { + +template +struct tagged_argument; + +template ::type +#endif + > +struct tag +{ + typedef tagged_argument< + Keyword + , typename unwrap_cv_reference::type + > type; +}; + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +struct tag +{ + typedef tagged_argument< + Keyword + , ActualArg + > type; +}; +#endif + +}}} // namespace boost::parameter::aux_ + +#endif // BOOST_PARAMETER_AUX_TAG_DWA2005610_HPP diff --git a/include/boost/parameter/aux_/tagged_argument.hpp b/include/boost/parameter/aux_/tagged_argument.hpp index 077160d..723ceea 100755 --- a/include/boost/parameter/aux_/tagged_argument.hpp +++ b/include/boost/parameter/aux_/tagged_argument.hpp @@ -19,8 +19,9 @@ struct tagged_argument { typedef Keyword key_type; typedef Arg value_type; + typedef Arg& reference; - tagged_argument(Arg& x) : value(x) {} + tagged_argument(reference x) : value(x) {} // Comma operator to compose argument list without using parameters<>. // Useful for argument lists with undetermined length. @@ -39,8 +40,8 @@ struct tagged_argument , arg_list >(x, empty_arg_list()) ); } - - Arg& value; + + reference value; }; // Defines a metafunction, is_tagged_argument, that identifies diff --git a/include/boost/parameter/aux_/unwrap_cv_reference.hpp b/include/boost/parameter/aux_/unwrap_cv_reference.hpp index 57cc9c9..e7aa0c1 100755 --- a/include/boost/parameter/aux_/unwrap_cv_reference.hpp +++ b/include/boost/parameter/aux_/unwrap_cv_reference.hpp @@ -37,9 +37,19 @@ struct is_cv_reference_wrapper ) ); - typedef mpl::bool_ type; + typedef mpl::bool_< +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + is_cv_reference_wrapper:: +#endif + value> type; }; +#if BOOST_WORKAROUND(MSVC, == 1200) +template <> +struct is_cv_reference_wrapper + : mpl::false_ {}; +#endif + // Needed for unwrap_cv_reference below. T might be const, so // eval_if might fail because of deriving from T const on EDG. template @@ -48,6 +58,25 @@ struct get_type typedef typename T::type type; }; +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template ::type> +struct unwrap_cv_reference +{ + typedef T type; +}; + +template +struct unwrap_cv_reference +{ + typedef T const type; +}; + +template +struct unwrap_cv_reference + : T +{}; + +#else // Produces the unwrapped type to hold a reference to in named<> // Can't use boost::unwrap_reference<> here because it // doesn't handle the case where T = reference_wrapper cv @@ -60,6 +89,7 @@ struct unwrap_cv_reference , mpl::identity >::type type; }; +#endif }}} // namespace boost::parameter::aux diff --git a/include/boost/parameter/keyword.hpp b/include/boost/parameter/keyword.hpp index 820b8cc..84d0975 100755 --- a/include/boost/parameter/keyword.hpp +++ b/include/boost/parameter/keyword.hpp @@ -7,7 +7,7 @@ #define KEYWORD_050328_HPP #include -#include +#include #include namespace boost { namespace parameter { @@ -31,16 +31,11 @@ template struct keyword { template - aux::tagged_argument< - Tag - , typename aux::unwrap_cv_reference::type - > + typename aux::tag::type operator=(T& x) const { - return aux::tagged_argument< - Tag - , BOOST_DEDUCED_TYPENAME aux::unwrap_cv_reference::type - >(x); + typedef typename aux::tag::type result; + return result(x); } template @@ -59,16 +54,11 @@ struct keyword #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // avoid partial ordering bugs template - aux::tagged_argument< - Tag - , typename aux::unwrap_cv_reference::type - > + typename aux::tag::type operator=(T const& x) const { - return aux::tagged_argument< - Tag - , BOOST_DEDUCED_TYPENAME aux::unwrap_cv_reference::type - >(x); + typedef typename aux::tag::type result; + return result(x); } #endif @@ -92,7 +82,7 @@ struct keyword { return aux::lazy_default(default_); } -#endif +#endif }; }} // namespace boost::parameter diff --git a/include/boost/parameter/macros.hpp b/include/boost/parameter/macros.hpp index 67c1e8b..4878d70 100755 --- a/include/boost/parameter/macros.hpp +++ b/include/boost/parameter/macros.hpp @@ -21,23 +21,35 @@ #define BOOST_PARAMETER_FUN_TEMPLATE_HEAD0(n) -#define BOOST_PARAMETER_FUN_DECL(z, n, params) \ - \ - BOOST_PP_CAT(BOOST_PARAMETER_FUN_TEMPLATE_HEAD, BOOST_PP_BOOL(n))(n) \ - \ - BOOST_PP_TUPLE_ELEM(3, 0, params) \ - BOOST_PP_TUPLE_ELEM(3, 1, params)( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& p) \ - BOOST_PP_COMMA_IF(n) \ - BOOST_PP_EXPR_IF(n, typename) BOOST_PP_TUPLE_ELEM(3, 2, params)::restrict \ - < \ - BOOST_PP_ENUM_PARAMS(n, T) \ - >::type kw = BOOST_PP_TUPLE_ELEM(3, 2, params)() \ - ) \ - { \ - return BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, params), _with_named_params)( \ - kw(BOOST_PP_ENUM_PARAMS(n, p)) \ - ); \ +#ifndef BOOST_NO_SFINAE + +# define BOOST_PARAMETER_RESTRICT_TYPE(n, param) \ + BOOST_PP_EXPR_IF(n, typename) param::restrict \ + < \ + BOOST_PP_ENUM_PARAMS(n, T) \ + >::type + +#else + +# define BOOST_PARAMETER_RESTRICT_TYPE(n, param) param + +#endif + +#define BOOST_PARAMETER_FUN_DECL(z, n, params) \ + \ + BOOST_PP_CAT(BOOST_PARAMETER_FUN_TEMPLATE_HEAD, BOOST_PP_BOOL(n))(n) \ + \ + BOOST_PP_TUPLE_ELEM(3, 0, params) \ + BOOST_PP_TUPLE_ELEM(3, 1, params)( \ + BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& p) \ + BOOST_PP_COMMA_IF(n) \ + BOOST_PARAMETER_RESTRICT_TYPE(n,BOOST_PP_TUPLE_ELEM(3, 2, params)) \ + kw = BOOST_PP_TUPLE_ELEM(3, 2, params)() \ + ) \ + { \ + return BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, params), _with_named_params)( \ + kw(BOOST_PP_ENUM_PARAMS(n, p)) \ + ); \ } // Generates: diff --git a/include/boost/parameter/parameters.hpp b/include/boost/parameter/parameters.hpp index 556ec9f..ebbd3ee 100755 --- a/include/boost/parameter/parameters.hpp +++ b/include/boost/parameter/parameters.hpp @@ -15,7 +15,9 @@ #include #include #include + #include +#include #include #include @@ -37,6 +39,7 @@ #include #include #include +#include #include namespace boost { @@ -179,17 +182,13 @@ namespace aux // already a tagged_argument template struct as_tagged_argument - { - typedef typename mpl::if_< + : mpl::eval_if< is_tagged_argument - , Arg - , tagged_argument< - typename key_type::type - , typename unwrap_cv_reference::type - > - >::type type; - }; - + , mpl::identity + , tag::type, Arg const> + > + {}; + #if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround template <> struct as_tagged_argument @@ -325,15 +324,19 @@ struct parameters {}; #endif - -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - // Specializations are to be used as an optional argument to // eliminate overloads via SFINAE template< +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + // Borland simply can't handle default arguments in member + // class templates. People wishing to write portable code can + // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments + BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, class A) +#else BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PARAMETER_MAX_ARITY, class A, = aux::void_ BOOST_PP_INTERCEPT - ) + ) +#endif > struct restrict # ifndef BOOST_NO_SFINAE @@ -351,8 +354,6 @@ struct parameters }; # endif -#endif - // // The function call operator is used to build an arg_list that // labels the positional parameters and maintains whatever other diff --git a/test/Jamfile b/test/Jamfile index 94c4159..4d235c7 100755 --- a/test/Jamfile +++ b/test/Jamfile @@ -5,11 +5,10 @@ subproject libs/parameter/test ; # bring in rules for testing import testing ; -{ - test-suite "parameter" - : [ run basics.cpp ] - [ run sfinae.cpp ] - [ run macros.cpp ] - ; +test-suite "parameter" + : [ run basics.cpp ] + [ run sfinae.cpp ] + [ run macros.cpp ] + [ compile unwrap_cv_reference.cpp ] + ; -} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a35e094..fcb27ec 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,7 +1,8 @@ # Boost Parameter Library test Jamfile - test-suite "parameter" - : [ run basics.cpp ] - [ run sfinae.cpp ] - [ run macros.cpp ] - ; +test-suite "parameter" + : [ run basics.cpp ] + [ run sfinae.cpp ] + [ run macros.cpp ] + [ compile unwrap_cv_reference.cpp ] + ; diff --git a/test/basics.cpp b/test/basics.cpp index bf791e1..f848efd 100755 --- a/test/basics.cpp +++ b/test/basics.cpp @@ -8,10 +8,10 @@ #include #include #include -#include #include "basics.hpp" + namespace test { // A separate function for getting the "value" key, so we can deduce diff --git a/test/basics.hpp b/test/basics.hpp index bb8a51e..6e78d4b 100755 --- a/test/basics.hpp +++ b/test/basics.hpp @@ -6,6 +6,8 @@ #ifndef BASICS_050424_HPP #define BASICS_050424_HPP +#include + namespace test { using namespace boost::parameter; @@ -50,6 +52,13 @@ inline bool equal(char const* s1, char const* s2) return !strcmp(s1,s2); } +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +inline bool equal(char* s1, char* s2) +{ + return !strcmp(s1,s2); +} +#endif + template struct values_t { @@ -64,9 +73,10 @@ struct values_t // Only VC and its emulators fail this; they seem to have // problems with deducing the constness of string literal // arrays. -#if defined(_MSC_VER) \ - && (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) \ - || BOOST_WORKAROUND(BOOST_MSVC, < 1310)) +#if defined(_MSC_VER) \ + && (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) \ + || BOOST_WORKAROUND(BOOST_MSVC, < 1310)) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # else BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -94,7 +104,7 @@ values(Name const& n, Value const& v, Index const& i) // GCC2 has a problem with char (&)[] deduction, so we'll cast string // literals there. #undef S -#if BOOST_WORKAROUND(__GNUC__, == 2) +#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # define S(s) (char const*)s #else # define S(s) s diff --git a/test/sfinae.cpp b/test/sfinae.cpp index db74db0..dc054ba 100755 --- a/test/sfinae.cpp +++ b/test/sfinae.cpp @@ -9,6 +9,11 @@ #include #include +#ifndef BOOST_NO_SFINAE +# include +# include +#endif + namespace test { using namespace boost::parameter; @@ -45,21 +50,45 @@ namespace test { f_impl(f_parameters()()); } + + using boost::parameter::aux::void_; template void f(A0 const& a0 - , typename f_parameters::restrict::type args = f_parameters()) + , typename f_parameters::restrict::type args = f_parameters()) { f_impl(args(a0)); } template void f(A0 const& a0, A1 const& a1 - , typename f_parameters::restrict::type args = f_parameters()) + , typename f_parameters::restrict::type args = f_parameters()) { f_impl(args(a0, a1)); } +#ifndef BOOST_NO_SFINAE + // On compilers that actually support SFINAE, add another overload + // that is an equally good match and can only be in the overload set + // when the others are not. This tests that the SFINAE is actually + // working. On all other compilers we're just checking that + // everything about SFINAE-enabled code will work, except of course + // the SFINAE. + template + typename boost::enable_if, int>::type + f(A0 const& a0, A1 const& a1) + { + return 0; + } +#endif } // namespace test int main() @@ -72,6 +101,10 @@ int main() f("foo", 3.f); f(value = 3.f, name = "foo"); +#ifndef BOOST_NO_SFINAE + return f(3, 4); +#else return 0; +#endif } diff --git a/test/unwrap_cv_reference.cpp b/test/unwrap_cv_reference.cpp new file mode 100755 index 0000000..5780e39 --- /dev/null +++ b/test/unwrap_cv_reference.cpp @@ -0,0 +1,30 @@ +// Copyright David Abrahams 2005. Distributed under 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 +#include +#include +#include + +namespace test +{ + using namespace boost::parameter::aux; + using namespace boost; + struct foo {}; + + BOOST_MPL_ASSERT((is_same::type,int>)); + BOOST_MPL_ASSERT((is_same::type,int const>)); + BOOST_MPL_ASSERT((is_same::type,int volatile>)); + BOOST_MPL_ASSERT((is_same::type,int const volatile>)); + + BOOST_MPL_ASSERT((is_same::type,foo>)); + BOOST_MPL_ASSERT((is_same::type,foo const>)); + BOOST_MPL_ASSERT((is_same::type,foo volatile>)); + BOOST_MPL_ASSERT((is_same::type,foo const volatile>)); + + BOOST_MPL_ASSERT((is_same >::type,foo>)); + BOOST_MPL_ASSERT((is_same const>::type,foo>)); + BOOST_MPL_ASSERT((is_same volatile>::type,foo>)); + BOOST_MPL_ASSERT((is_same const volatile>::type,foo>)); +}