diff --git a/include/boost/unordered/detail/foa/takes_arg_as_const_reference.hpp b/include/boost/unordered/detail/foa/takes_arg_as_const_reference.hpp index 3a5c69d5..26cc7a57 100644 --- a/include/boost/unordered/detail/foa/takes_arg_as_const_reference.hpp +++ b/include/boost/unordered/detail/foa/takes_arg_as_const_reference.hpp @@ -18,75 +18,37 @@ namespace unordered{ namespace detail{ namespace foa{ -static constexpr bool noexcept_is_part_of_signature= - !std::is_same::value; - -template -static std::false_type has_1st_arg(Sig); +template +void check_function_1st_arg(R(*)(Arg,Args...)); template -static std::true_type has_1st_arg(R(*)(Arg,Args...)); +void check_function_1st_arg(R(*)(Arg,Args...,...)); -template< - typename Arg,typename R,typename... Args, - bool dependent_value=false, - typename std::enable_if< - noexcept_is_part_of_signature||dependent_value>::type* =nullptr -> -static std::true_type has_1st_arg(R(*)(Arg,Args...)noexcept); - -template -static std::true_type has_1st_arg(R(*)(Arg,Args...,...)); - -template< - typename Arg,typename R,typename... Args, - bool dependent_value=false, - typename std::enable_if< - noexcept_is_part_of_signature||dependent_value>::type* =nullptr -> -std::true_type has_1st_arg(R(*)(Arg,Args...,...)noexcept); - -#define BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(qualifier) \ -template \ -static std::true_type has_1st_arg(R(C::*)(Arg,Args...)qualifier); \ - \ -template< \ - typename Arg,typename R,typename C,typename... Args, \ - bool dependent_value=false, \ - typename std::enable_if< \ - noexcept_is_part_of_signature||dependent_value>::type* =nullptr \ -> \ -static std::true_type has_1st_arg(R(C::*)(Arg,Args...)qualifier noexcept); \ - \ -template \ -static std::true_type has_1st_arg(R(C::*)(Arg,Args...,...)qualifier); \ - \ -template< \ - typename Arg,typename R,typename C,typename... Args, \ - bool dependent_value=false, \ - typename std::enable_if< \ - noexcept_is_part_of_signature||dependent_value>::type* =nullptr \ -> \ -static std::true_type has_1st_arg(R(C::*)(Arg,Args...,...)qualifier noexcept); +#define BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(qualifier) \ +template \ +void check_memfun_1st_arg(R(C::*)(Arg,Args...)qualifier); \ + \ +template \ +void check_memfun_1st_arg(R(C::*)(Arg,Args...,...)qualifier); /* VS warns when a pp function is directly called with an empty arg */ #define BOOST_UNORDERED_EMPTY_PP_ARG() -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(BOOST_UNORDERED_EMPTY_PP_ARG()) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(&&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const&&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(volatile&&) -BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile&&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(BOOST_UNORDERED_EMPTY_PP_ARG()) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(volatile) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const volatile) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(volatile&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const volatile&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(&&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const&&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(volatile&&) +BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG(const volatile&&) #undef BOOST_UNORDERED_EMPTY_PP_ARG -#undef BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN +#undef BOOST_UNORDERED_CHECK_MEMFUN_1ST_ARG /* Detects if f(x) takes x as a const reference. From an implementation * technique by Kenneth Gorking. @@ -94,29 +56,41 @@ BOOST_UNORDERED_HAS_CONST_REFERENCE_ARG_MEMFUN(const volatile&&) */ template -struct takes_arg_as_const_reference0: -decltype(has_1st_arg(std::declval())){}; +struct takes_arg_as_const_reference0:std::false_type{}; template struct takes_arg_as_const_reference0< F,Arg, boost::void_t< - decltype(has_1st_arg(&F::template operator())) + decltype(check_function_1st_arg(std::declval())) > ->: -decltype(has_1st_arg(&F::template operator())){}; +>:std::true_type{}; + +template +struct takes_arg_as_const_reference0< + F,Arg, + boost::void_t< + decltype(std::declval().operator()(std::declval())) + > +>:std::true_type{}; template struct takes_arg_as_const_reference:takes_arg_as_const_reference0{}; +template< + typename F,typename Arg, + typename R=decltype(std::declval()(std::declval())), + typename RawF= + typename std::remove_cv::type>::type +> +using check_operator_call_takes_arg_as_reference= + decltype(check_memfun_1st_arg(&RawF::operator())); + template struct takes_arg_as_const_reference< F,Arg, - boost::void_t< - decltype(has_1st_arg(&F::operator())) - > ->: -decltype(has_1st_arg(&F::operator())){}; + boost::void_t> +>:std::false_type{}; } /* namespace foa */ } /* namespace detail */ diff --git a/test/cfoa/takes_arg_as_cref_tests.cpp b/test/cfoa/takes_arg_as_cref_tests.cpp index 2cfa1b05..2d7500f0 100644 --- a/test/cfoa/takes_arg_as_cref_tests.cpp +++ b/test/cfoa/takes_arg_as_cref_tests.cpp @@ -78,9 +78,9 @@ int main() int retrieved=0; auto lambda54 = [&]( const int& x ) mutable { retrieved = x; }; using f54=decltype(lambda54); - auto lambda55 = []( int& ){}; + auto lambda55 = []( int& x ){ x = 0; }; using f55=decltype(lambda55); - auto lambda56 = [&]( int& x ) mutable { retrieved = x; }; + auto lambda56 = [&]( int& x ) mutable { retrieved = x; x = 0; }; using f56=decltype(lambda56); #if !defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) @@ -88,90 +88,90 @@ int main() using f57=decltype(lambda57); auto lambda58 = [&]( const auto& x ) mutable { retrieved = x; }; using f58=decltype(lambda58); - auto lambda59 = []( auto& ){}; + auto lambda59 = []( auto& x ){ x = 0; }; using f59=decltype(lambda59); - auto lambda60 = [&]( auto& x ) mutable { retrieved = x; }; + auto lambda60 = [&]( auto& x ) mutable { retrieved = x; x = 0; }; using f60=decltype(lambda60); #endif - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); #if !defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); - BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); + BOOST_TEST(( !takes_arg_as_const_reference::value )); #endif return boost::report_errors();