// 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 #include #include #include #include #include #include "basics.hpp" #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include #include #include #include #else #include #include #include #if !defined(BOOST_NO_SFINAE) #include #include #include #include #endif #endif namespace test { BOOST_PARAMETER_NAME(expected) BOOST_PARAMETER_NAME(x) BOOST_PARAMETER_NAME(y) BOOST_PARAMETER_NAME(z) #if defined(BOOST_PARAMETER_CAN_USE_MP11) template struct predicate { template using fn = std::is_convertible; }; BOOST_PARAMETER_FUNCTION((int), f, test::tag, (required (expected, *) ) (deduced (required (x, *(test::predicate)) (y, *(test::predicate)) ) ) ) #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) struct predicate_int { template struct apply : boost::mpl::if_< boost::is_convertible , boost::mpl::true_ , boost::mpl::false_ > { }; }; struct predicate_string { template struct apply : boost::mpl::if_< boost::is_convertible , 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; } struct X { X(int x_ = -1) : x(x_) { } bool operator==(X const& other) const { return this->x == other.x; } int x; }; #if defined(BOOST_PARAMETER_CAN_USE_MP11) BOOST_PARAMETER_FUNCTION((int), g, test::tag, (required (expected, *) ) (deduced (required (x, *(test::predicate)) (y, *(test::predicate)) ) (optional (z, *(test::predicate), test::X()) ) ) ) #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) struct predicate_X { template struct apply : boost::mpl::if_< boost::is_convertible , boost::mpl::true_ , boost::mpl::false_ > { }; }; 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()) ) ) ) #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)) ) ) ) #else BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag, (deduced (required (x, *(test::predicate_string)) ) ) ) #endif { return 1; } #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 boost::enable_if< #if defined(BOOST_PARAMETER_CAN_USE_MP11) std::is_same #else typename boost::mpl::if_< boost::is_same , boost::mpl::true_ , boost::mpl::false_ >::type #endif , int >::type sfinae(A0 const& a0) { return 0; } #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 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)) ) ) ) { 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- // 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 , boost::parameter::value_type > ), return_y, test::tag, (deduced (required (x, (std::map)) (y, (char const*)) ) (optional (z, (int), 4) ) ) ) #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) BOOST_PARAMETER_FUNCTION( ( boost::lazy_enable_if< typename boost::mpl::has_key::type , boost::parameter::value_type > ), return_y, test::tag, (deduced (required (x, (std::map)) (y, (char const*)) ) (optional (z, (int), 4) ) ) ) #endif // BOOST_PARAMETER_CAN_USE_MP11 { return y; } #endif // LIBS_PARAMETER_TEST_COMPILE_FAILURE #endif // BOOST_NO_SFINAE #if defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) BOOST_PARAMETER_FUNCTION( (typename boost::parameter::value_type::type), return_y, test::tag, (deduced (required (x, (std::map)) (y, (char const*)) ) (optional (z, (int), 4) ) ) ) { return y; } #endif // defined(LIBS_PARAMETER_TEST_COMPILE_FAILURE) } // namespace test #include int main() { 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 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 boost::report_errors(); }