// 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 "basics.hpp" #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include #else #include #include #include #endif namespace test { BOOST_PARAMETER_BASIC_FUNCTION((int), f, test::tag, (required (tester, *) (name, *) ) (optional (value, *) (index, (int)) ) ) { typedef typename boost::parameter::binding< Args,test::tag::index,int& >::type index_type; #if defined(BOOST_PARAMETER_CAN_USE_MP11) static_assert( std::is_same::value , "index_type == int&" ); #else BOOST_MPL_ASSERT(( typename boost::mpl::if_< boost::is_same , boost::mpl::true_ , boost::mpl::false_ >::type )); #endif args[test::_tester]( args[test::_name] , args[test::_value | 1.f] , args[test::_index | 2] ); return 1; } } // namespace test #include #if !defined(BOOST_PARAMETER_CAN_USE_MP11) #include #endif namespace test { BOOST_PARAMETER_BASIC_FUNCTION((int), g, test::tag, (required (tester, *) (name, *) ) (optional (value, *) (index, (int)) ) ) { typedef typename boost::parameter::value_type< Args,test::tag::index,int >::type index_type; #if defined(BOOST_PARAMETER_CAN_USE_MP11) static_assert( std::is_same< typename std::remove_const::type , int >::value , "remove_const::type == int" ); #else BOOST_MPL_ASSERT(( typename boost::mpl::if_< boost::is_same< typename boost::remove_const::type , int > , boost::mpl::true_ , boost::mpl::false_ >::type )); #endif args[test::_tester]( args[test::_name] , args[test::_value | 1.f] , args[test::_index | 2] ); return 1; } } // namespace test #if !defined(BOOST_PARAMETER_CAN_USE_MP11) #include #endif namespace test { BOOST_PARAMETER_FUNCTION((int), h, test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, (int), 2) ) ) { #if defined(BOOST_PARAMETER_CAN_USE_MP11) static_assert( std::is_same< typename std::remove_const< typename std::remove_reference::type >::type , int >::value , "remove_cref::type == int" ); #elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) BOOST_MPL_ASSERT(( typename boost::mpl::if_< boost::is_same< typename boost::remove_const< typename boost::remove_reference::type >::type , int > , boost::mpl::true_ , boost::mpl::false_ >::type )); #endif // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed tester(name, value, index); return 1; } BOOST_PARAMETER_FUNCTION((int), h2, test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, (int), static_cast(value * 2)) ) ) { #if defined(BOOST_PARAMETER_CAN_USE_MP11) static_assert( std::is_same< typename std::remove_const< typename std::remove_reference::type >::type , int >::value , "remove_cref::type == int" ); #elif !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) BOOST_MPL_ASSERT(( typename boost::mpl::if_< boost::is_same< typename boost::remove_const< typename boost::remove_reference::type >::type , int > , boost::mpl::true_ , boost::mpl::false_ >::type )); #endif // BOOST_PARAMETER_CAN_USE_MP11 || Borland/MSVC workarounds not needed tester(name, value, index); return 1; } } // namespace test #include #if !defined(BOOST_NO_SFINAE) #include #include #if !defined(BOOST_PARAMETER_CAN_USE_MP11) #include #include #endif #endif namespace test { struct base_0 { float f; int i; template explicit base_0( Args const& args #if !defined(BOOST_NO_SFINAE) , typename boost::disable_if< typename boost::mpl::if_< boost::is_base_of , boost::mpl::true_ , boost::mpl::false_ >::type >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR #endif // BOOST_NO_SFINAE ) : f(args[test::_value | 1.f]), i(args[test::_index | 2]) { } }; struct class_0 : test::base_0 { BOOST_PARAMETER_CONSTRUCTOR(class_0, (test::base_0), test::tag, (optional (value, *) (index, *) ) ) BOOST_PARAMETER_BASIC_FUNCTION_CALL_OPERATOR((int), test::tag, (optional (value, *) (index, *) ) ) { this->f = args[test::_value | 2.f]; this->i = args[test::_index | 1]; return 1; } }; struct base_1 { template explicit base_1( Args const& args #if !defined(BOOST_NO_SFINAE) , typename boost::disable_if< #if defined(BOOST_PARAMETER_CAN_USE_MP11) std::is_base_of #else typename boost::mpl::if_< boost::is_base_of , boost::mpl::true_ , boost::mpl::false_ >::type #endif >::type* = BOOST_PARAMETER_AUX_PP_NULLPTR #endif // BOOST_NO_SFINAE ) { args[test::_tester]( args[test::_name] , args[test::_value | 1.f] , args[test::_index | 2] ); } }; struct class_1 : test::base_1 { BOOST_PARAMETER_CONSTRUCTOR(class_1, (test::base_1), test::tag, (required (tester, *) (name, *) ) (optional (value, *) (index, *) ) ) BOOST_PARAMETER_BASIC_MEMBER_FUNCTION((int), f, test::tag, (required (tester, *) (name, *) ) (optional (value, *) (index, *) ) ) { args[test::_tester]( args[test::_name] , args[test::_value | 1.f] , args[test::_index | 2] ); return 1; } BOOST_PARAMETER_BASIC_CONST_MEMBER_FUNCTION((int), f, test::tag, (required (tester, *) (name, *) ) (optional (value, *) (index, *) ) ) { args[test::_tester]( args[test::_name] , args[test::_value | 1.f] , args[test::_index | 2] ); return 1; } BOOST_PARAMETER_MEMBER_FUNCTION((int), f2, test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, *, 2) ) ) { tester(name, value, index); return 1; } BOOST_PARAMETER_CONST_MEMBER_FUNCTION((int), f2, test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, *, 2) ) ) { tester(name, value, index); return 1; } BOOST_PARAMETER_MEMBER_FUNCTION((int), static f_static, test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, *, 2) ) ) { tester(name, value, index); return 1; } BOOST_PARAMETER_FUNCTION_CALL_OPERATOR((int), test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, *, 2) ) ) { tester(name, value, index); return 1; } BOOST_PARAMETER_CONST_FUNCTION_CALL_OPERATOR((int), test::tag, (required (tester, *) (name, *) ) (optional (value, *, 1.f) (index, *, 2) ) ) { tester(name, value, index); return 1; } }; BOOST_PARAMETER_FUNCTION((int), sfinae, test::tag, (required (name, (std::string)) ) ) { 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; } #endif // BOOST_NO_SFINAE struct predicate { template #if defined(BOOST_PARAMETER_CAN_USE_MP11) using fn = std::is_convertible; #else struct apply : boost::mpl::if_< boost::is_convertible , boost::mpl::true_ , boost::mpl::false_ > { }; #endif BOOST_PARAMETER_BASIC_CONST_FUNCTION_CALL_OPERATOR((bool), test::tag, (required (value, *) (index, *) ) ) { return args[test::_value] < args[test::_index]; } }; BOOST_PARAMETER_FUNCTION((int), sfinae1, test::tag, (required (name, *(test::predicate)) ) ) { 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 sfinae1(A0 const& a0) { return 0; } #endif // BOOST_NO_SFINAE struct udt { udt(int foo_, int bar_) : foo(foo_), bar(bar_) { } int foo; int bar; }; BOOST_PARAMETER_FUNCTION((int), lazy_defaults, test::tag, (required (name, *) ) (optional (value, *, name.foo) (index, *, name.bar) ) ) { return 0; } } // namespace test #if BOOST_WORKAROUND(BOOST_MSVC, == 1300) #include #endif #include int main() { test::f( test::values(std::string("foo"), 1.f, 2) , std::string("foo") ); test::f( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); int index_lvalue = 2; test::f( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") , test::_value = 1.f , test::_index = index_lvalue ); test::f( test::values(std::string("foo"), 1.f, 2) , std::string("foo") , 1.f , index_lvalue ); test::g( test::values(std::string("foo"), 1.f, 2) , std::string("foo") , 1.f #if BOOST_WORKAROUND(BOOST_MSVC, == 1300) , boost::parameter::aux::as_lvalue(2) #else , 2 #endif ); test::h( test::values(std::string("foo"), 1.f, 2) , std::string("foo") , 1.f #if BOOST_WORKAROUND(BOOST_MSVC, == 1300) , boost::parameter::aux::as_lvalue(2) #else , 2 #endif ); test::h2( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") , test::_value = 1.f ); test::class_0 u; BOOST_TEST(2 == u.i); BOOST_TEST(1.f == u.f); u(); BOOST_TEST(1 == u.i); BOOST_TEST(2.f == u.f); test::class_1 x( test::values(std::string("foo"), 1.f, 2) , std::string("foo") , test::_index = 2 ); x.f(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x.f( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); x.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x.f2( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); x(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); test::class_1 const& x_const = x; x_const.f(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x_const.f( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); x_const.f2(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x_const.f2( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); test::class_1::f_static( test::values(std::string("foo"), 1.f, 2) , std::string("foo") ); test::class_1::f_static( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); x_const(test::values(std::string("foo"), 1.f, 2), std::string("foo")); x_const( test::_tester = test::values(std::string("foo"), 1.f, 2) , test::_name = std::string("foo") ); test::predicate p; test::predicate const& p_const = p; BOOST_TEST(p_const(3, 4)); BOOST_TEST(!p_const(4, 3)); BOOST_TEST(!p_const(test::_index = 3, test::_value = 4)); #if !defined(BOOST_NO_SFINAE) && \ !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) // GCC 3- tries to bind string literals // to non-const references to char const*. // BOOST_TEST(test::sfinae("foo") == 1); char const* foo_str = "foo"; BOOST_TEST(test::sfinae(foo_str) == 1); BOOST_TEST(test::sfinae(1) == 0); #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) // Sun actually eliminates the desired overload for some reason. // Disabling this part of the test because SFINAE abilities are // not the point of this test. BOOST_TEST(test::sfinae1(foo_str) == 1); #endif BOOST_TEST(test::sfinae1(1) == 0); #endif test::lazy_defaults(test::_name = test::udt(0, 1)); test::lazy_defaults(test::_name = 0, test::_value = 1, test::_index = 2); return boost::report_errors(); }