/*! @file @Copyright Barrett Adair 2015-2017 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP #define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP #include #include #include #include #include namespace boost { namespace callable_traits { namespace detail { template struct can_dereference_t { template struct check {}; template static std::int8_t test( check())>::type>* ); template static std::int16_t test(...); static constexpr const bool value = sizeof(test(nullptr)) == sizeof(std::int8_t); }; //returns std::true_type for pointers and smart pointers template using can_dereference = std::integral_constant::value>; template struct generalize_t { using type = T; }; template struct generalize_t::value && !is_reference_wrapper::value >>{ using type = decltype(*std::declval()); }; template struct generalize_t> { using type = decltype(std::declval().get()); }; // When T is a pointer, generalize is the resulting type of the // pointer dereferenced. When T is an std::reference_wrapper, generalize // is the underlying reference type. Otherwise, generalize is T. template using generalize = typename generalize_t::type; // handles the member pointer rules of INVOKE template>, typename IsSame = std::is_same>> using generalize_if_dissimilar = typename std::conditional< IsBaseOf::value || IsSame::value, T, generalize>::type; template struct test_invoke { template auto operator()(int, Rgs&&... rgs) const -> success()(static_cast(rgs)...))>; auto operator()(long, ...) const -> substitution_failure; }; template struct test_invoke, true /*abominable*/> { auto operator()(...) const -> substitution_failure; }; template struct test_invoke, Ignored> { using class_t = typename pmf::class_type; template> auto operator()(int, U&& u, Rgs&&... rgs) const -> success().*std::declval())(static_cast(rgs)...))>; auto operator()(long, ...) const -> substitution_failure; }; template struct test_invoke, Ignored> { using class_t = typename pmd::class_type; template> auto operator()(int, U&& u) const -> success().*std::declval())>; auto operator()(long, ...) const -> substitution_failure; }; template struct is_invocable_impl { using traits = detail::traits; using test = detail::test_invoke; using result = decltype(test{}(0, ::std::declval()...)); using type = std::integral_constant; }; template struct is_invocable_impl { using type = std::false_type; }; template struct is_invocable_r_impl { using traits = detail::traits; using test = detail::test_invoke; using result = decltype(test{}(0, ::std::declval()...)); using type = std::integral_constant::value || std::is_same::value>; }; template struct is_invocable_r_impl { using type = std::false_type; }; }}} // namespace boost::callable_traits::detail #endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP