-// Copyright Daniel Wallin 2006. 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)
+// Copyright Daniel Wallin 2006.
+// 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 <boost/parameter/config.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <boost/parameter/name.hpp>
-#include <boost/type_traits/is_convertible.hpp>
#include <boost/tuple/tuple.hpp>
+#include <map>
#include <string>
#include "basics.hpp"
-#ifndef BOOST_NO_SFINAE
-# include <boost/utility/enable_if.hpp>
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/parameter/value_type.hpp>
+#include <boost/mp11/map.hpp>
+#include <boost/core/enable_if.hpp>
+#include <type_traits>
+#else
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#if !defined(BOOST_NO_SFINAE)
+#include <boost/parameter/value_type.hpp>
+#include <boost/mpl/has_key.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif
#endif
namespace test {
-namespace mpl = boost::mpl;
+ BOOST_PARAMETER_NAME(expected)
+ BOOST_PARAMETER_NAME(x)
+ BOOST_PARAMETER_NAME(y)
+ BOOST_PARAMETER_NAME(z)
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ template <typename To>
+ struct predicate
+ {
+ template <typename From, typename Args>
+ using fn = std::is_convertible<From,To>;
+ };
+
+ BOOST_PARAMETER_FUNCTION((int), f, test::tag,
+ (required
+ (expected, *)
+ )
+ (deduced
+ (required
+ (x, *(test::predicate<int>))
+ (y, *(test::predicate<std::string>))
+ )
+ )
+ )
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ struct predicate_int
+ {
+ template <typename From, typename Args>
+ struct apply
+ : boost::mpl::if_<
+ boost::is_convertible<From,int>
+ , boost::mpl::true_
+ , boost::mpl::false_
+ >
+ {
+ };
+ };
+
+ struct predicate_string
+ {
+ template <typename From, typename Args>
+ struct apply
+ : boost::mpl::if_<
+ boost::is_convertible<From,std::string>
+ , boost::mpl::true_
+ , boost::mpl::false_
+ >
+ {
+ };
+ };
+
+ BOOST_PARAMETER_FUNCTION((int), f, test::tag,
+ (required
+ (expected, *)
+ )
+ (deduced
+ (required
+ (x, *(test::predicate_int))
+ (y, *(test::predicate_string))
+ )
+ )
+ )
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ {
+ BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected)));
+ BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected)));
+ return 1;
+ }
-using mpl::_;
-using boost::is_convertible;
+ struct X
+ {
+ X(int x_ = -1) : x(x_)
+ {
+ }
-BOOST_PARAMETER_NAME(expected)
-BOOST_PARAMETER_NAME(x)
-BOOST_PARAMETER_NAME(y)
-BOOST_PARAMETER_NAME(z)
+ bool operator==(X const& other) const
+ {
+ return this->x == other.x;
+ }
-// Sun has problems with this syntax:
-//
-// template1< r* ( template2<x> ) >
-//
-// Workaround: factor template2<x> into a separate typedef
-typedef is_convertible<_, int> predicate1;
-typedef is_convertible<_, std::string> predicate2;
+ int x;
+ };
-#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ BOOST_PARAMETER_FUNCTION((int), g, test::tag,
+ (required
+ (expected, *)
+ )
+ (deduced
+ (required
+ (x, *(test::predicate<int>))
+ (y, *(test::predicate<std::string>))
+ )
+ (optional
+ (z, *(test::predicate<test::X>), test::X())
+ )
+ )
+ )
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ struct predicate_X
+ {
+ template <typename From, typename Args>
+ struct apply
+ : boost::mpl::if_<
+ boost::is_convertible<From,test::X>
+ , boost::mpl::true_
+ , boost::mpl::false_
+ >
+ {
+ };
+ };
-BOOST_PARAMETER_FUNCTION((int), f, tag,
- (required
- (expected, *)
+ BOOST_PARAMETER_FUNCTION((int), g, tag,
+ (required
+ (expected, *)
+ )
+ (deduced
+ (required
+ (x, *(test::predicate_int))
+ (y, *(test::predicate_string))
+ )
+ (optional
+ (z, *(test::predicate_X), test::X())
+ )
+ )
)
- (deduced
- (required
- (x, *(predicate1))
- (y, *(predicate2))
- )
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ {
+ BOOST_TEST(test::equal(x, boost::tuples::get<0>(expected)));
+ BOOST_TEST(test::equal(y, boost::tuples::get<1>(expected)));
+ BOOST_TEST(test::equal(z, boost::tuples::get<2>(expected)));
+ return 1;
+ }
+
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
+ (deduced
+ (required
+ (x, *(test::predicate<std::string>))
+ )
+ )
)
-)
#else
-BOOST_PARAMETER_FUNCTION((int), f, tag,
- (required
- (expected, *)
+ BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag,
+ (deduced
+ (required
+ (x, *(test::predicate_string))
+ )
+ )
)
- (deduced
- (required
- (x, *(is_convertible<_, int>))
- (y, *(is_convertible<_, std::string>))
- )
- )
-)
-#endif
-{
- assert(equal(x, boost::tuples::get<0>(expected)));
- assert(equal(y, boost::tuples::get<1>(expected)));
- return 1;
-}
+#endif
+ {
+ return 1;
+ }
-struct X
-{
- X(int x = -1)
- : x(x)
- {}
-
- bool operator==(X const& other) const
+#if !defined(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 A0>
+ typename boost::enable_if<
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ std::is_same<int,A0>
+#else
+ typename boost::mpl::if_<
+ boost::is_same<int,A0>
+ , boost::mpl::true_
+ , boost::mpl::false_
+ >::type
+#endif
+ , int
+ >::type
+ sfinae(A0 const& a0)
{
- return x == other.x;
+ return 0;
}
-
- int x;
-};
-typedef is_convertible<_, X> predicate3; // SunPro workaround; see above
+#if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \
+ !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ // Test support for two different Boost.Parameter-enabled
+ // function call operator overloads.
+ class char_read_base
+ {
+ int index;
+ char const* key;
+
+ public:
+ template <typename Args>
+ explicit char_read_base(Args const& args)
+ : index(args[test::_y]), key(args[test::_z])
+ {
+ }
+
+ BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((void), test::tag,
+ (deduced
+ (required
+ (y, (int))
+ (z, (char const*))
+ )
+ )
+ )
+ {
+ this->index = y;
+ this->key = z;
+ }
+
+ BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((char), test::tag,
+ (deduced
+ (required
+ (y, (bool))
+ (z, (std::map<char const*,std::string>))
+ )
+ )
+ )
+ {
+ return y ? (
+ (z.find(this->key)->second)[this->index]
+ ) : this->key[this->index];
+ }
+ };
+
+ struct char_reader : public char_read_base
+ {
+ BOOST_PARAMETER_CONSTRUCTOR(char_reader, (char_read_base), test::tag,
+ (deduced
+ (required
+ (y, (int))
+ (z, (char const*))
+ )
+ )
+ )
+ };
+#endif // MSVC-11.0-
-BOOST_PARAMETER_FUNCTION((int), g, tag,
- (required
- (expected, *)
+ // Test Boost.Parameter-enabled functions
+ // with parameter-dependent return types.
+#if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+ BOOST_PARAMETER_FUNCTION(
+ (
+ boost::lazy_enable_if<
+ boost::mp11::mp_map_contains<Args,test::tag::y>
+ , boost::parameter::value_type<Args,test::tag::y>
+ >
+ ), return_y, test::tag,
+ (deduced
+ (required
+ (x, (std::map<char const*,std::string>))
+ (y, (char const*))
+ )
+ (optional
+ (z, (int), 4)
+ )
+ )
)
- (deduced
- (required
- (x, *(is_convertible<_, int>))
- (y, *(is_convertible<_, std::string>))
- )
- (optional
- (z, *(predicate3), X())
- )
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+ BOOST_PARAMETER_FUNCTION(
+ (
+ boost::lazy_enable_if<
+ typename boost::mpl::has_key<Args,test::tag::y>::type
+ , boost::parameter::value_type<Args,test::tag::y>
+ >
+ ), return_y, test::tag,
+ (deduced
+ (required
+ (x, (std::map<char const*,std::string>))
+ (y, (char const*))
+ )
+ (optional
+ (z, (int), 4)
+ )
+ )
)
-)
-{
- assert(equal(x, boost::tuples::get<0>(expected)));
- assert(equal(y, boost::tuples::get<1>(expected)));
- assert(equal(z, boost::tuples::get<2>(expected)));
- return 1;
-}
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+ {
+ return y;
+ }
+#endif // LIBS_PARAMETER_TEST_COMPILE_FAILURE
+#endif // BOOST_NO_SFINAE
-BOOST_PARAMETER_FUNCTION(
- (int), sfinae, tag,
- (deduced
- (required
- (x, *(predicate2))
- )
+#if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
+ BOOST_PARAMETER_FUNCTION(
+ (typename boost::parameter::value_type<Args,test::tag::y>::type),
+ return_y, test::tag,
+ (deduced
+ (required
+ (x, (std::map<char const*,std::string>))
+ (y, (char const*))
+ )
+ (optional
+ (z, (int), 4)
+ )
+ )
)
-)
-{
- return 1;
-}
-
-#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<class A0>
-typename boost::enable_if<boost::is_same<int,A0>, int>::type
-sfinae(A0 const& a0)
-{
- return 0;
-}
-#endif
-
+ {
+ return y;
+ }
+#endif // defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
} // namespace test
-using boost::make_tuple;
-
-// make_tuple doesn't work with char arrays.
-char const* str(char const* s)
-{
- return s;
-}
+#include <boost/core/lightweight_test.hpp>
int main()
{
- using namespace test;
-
- f(make_tuple(0, str("foo")), _x = 0, _y = "foo");
- f(make_tuple(0, str("foo")), _x = 0, _y = "foo");
- f(make_tuple(0, str("foo")), 0, "foo");
- f(make_tuple(0, str("foo")), "foo", 0);
- f(make_tuple(0, str("foo")), _y = "foo", 0);
- f(make_tuple(0, str("foo")), _x = 0, "foo");
- f(make_tuple(0, str("foo")), 0, _y = "foo");
-
- g(make_tuple(0, str("foo"), X()), _x = 0, _y = "foo");
- g(make_tuple(0, str("foo"), X()), 0, "foo");
- g(make_tuple(0, str("foo"), X()), "foo", 0);
- g(make_tuple(0, str("foo"), X()), _y = "foo", 0);
- g(make_tuple(0, str("foo"), X()), _x = 0, "foo");
- g(make_tuple(0, str("foo"), X()), 0, _y = "foo");
-
- g(make_tuple(0, str("foo"), X(1)), 0, _y = "foo", X(1));
- g(make_tuple(0, str("foo"), X(1)), X(1), 0, _y = "foo");
-
-#ifndef BOOST_NO_SFINAE
- assert(sfinae("foo") == 1);
- assert(sfinae(0) == 0);
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , test::_x = 0
+ , test::_y = std::string("foo")
+ );
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , 0
+ , std::string("foo")
+ );
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , std::string("foo")
+ , 0
+ );
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , test::_y = std::string("foo")
+ , 0
+ );
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , test::_x = 0
+ , std::string("foo")
+ );
+ test::f(
+ boost::make_tuple(0, std::string("foo"))
+ , 0
+ , test::_y = std::string("foo")
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , test::_x = 0
+ , test::_y = std::string("foo")
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , 0
+ , std::string("foo")
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , std::string("foo")
+ , 0
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , test::_y = std::string("foo")
+ , 0
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , test::_x = 0
+ , std::string("foo")
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X())
+ , 0
+ , test::_y = std::string("foo")
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X(1))
+ , 0
+ , test::_y = std::string("foo")
+ , test::X(1)
+ );
+ test::g(
+ boost::make_tuple(0, std::string("foo"), test::X(1))
+ , test::X(1)
+ , 0
+ , test::_y = std::string("foo")
+ );
+
+ std::map<char const*,std::string> k2s;
+#if !defined(BOOST_NO_SFINAE)
+ char const* keys[] = {"foo", "bar", "baz"};
+ BOOST_TEST_EQ(1, test::sfinae(keys[0]));
+ BOOST_TEST_EQ(0, test::sfinae(0));
+#if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE_VENDOR_SPECIFIC) || \
+ !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ k2s[keys[0]] = std::string("qux");
+ k2s[keys[1]] = std::string("wmb");
+ k2s[keys[2]] = std::string("zxc");
+ test::char_reader r(keys[0], 0);
+ BOOST_TEST_EQ('q', (r(k2s, true)));
+ BOOST_TEST_EQ('f', (r(k2s, false)));
+ r(keys[1], 1);
+ BOOST_TEST_EQ('m', (r(k2s, true)));
+ BOOST_TEST_EQ('a', (r(k2s, false)));
+ r(keys[2], 2);
+ BOOST_TEST_EQ('c', (r(k2s, true)));
+ BOOST_TEST_EQ('z', (r(k2s, false)));
+#endif // MSVC-11.0-
+#if !defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
+ BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1]));
+#endif
+#endif // BOOST_NO_SFINAE
+
+#if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE)
+ BOOST_TEST_EQ(keys[1], test::return_y(2, k2s, keys[1]));
#endif
- return 0;
+ return boost::report_errors();
}