Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:45

0001  /*!
0002 @file
0003 
0004 @Copyright Barrett Adair 2015-2017
0005 Distributed under the Boost Software License, Version 1.0.
0006 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0007 
0008 */
0009 
0010 #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
0011 #define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
0012 
0013 #include <boost/callable_traits/detail/config.hpp>
0014 #include <boost/callable_traits/detail/forward_declarations.hpp>
0015 #include <boost/callable_traits/detail/utility.hpp>
0016 #include <type_traits>
0017 #include <utility>
0018 
0019 namespace boost { namespace callable_traits { namespace detail {
0020 
0021     template<typename T>
0022     struct can_dereference_t
0023     {
0024         template<typename>
0025         struct check {};
0026 
0027         template<typename U>
0028         static std::int8_t test(
0029             check<typename std::remove_reference<decltype(*std::declval<U>())>::type>*
0030         );
0031 
0032         template<typename>
0033         static std::int16_t test(...);
0034 
0035         static constexpr const bool value =
0036             sizeof(test<T>(nullptr)) == sizeof(std::int8_t);
0037     };
0038 
0039     //returns std::true_type for pointers and smart pointers
0040     template<typename T>
0041     using can_dereference = std::integral_constant<bool,
0042         can_dereference_t<T>::value>;
0043 
0044 
0045     template<typename T, typename = std::true_type>
0046     struct generalize_t {
0047         using type = T;
0048     };
0049 
0050     template<typename T>
0051     struct generalize_t<T, std::integral_constant<bool,
0052             can_dereference<T>::value && !is_reference_wrapper<T>::value
0053     >>{
0054         using type = decltype(*std::declval<T>());
0055     };
0056 
0057     template<typename T>
0058     struct generalize_t<T, is_reference_wrapper<T>> {
0059         using type = decltype(std::declval<T>().get());
0060     };
0061 
0062     // When T is a pointer, generalize<T> is the resulting type of the
0063     // pointer dereferenced. When T is an std::reference_wrapper, generalize<T>
0064     // is the underlying reference type. Otherwise, generalize<T> is T.
0065     template<typename T>
0066     using generalize = typename generalize_t<T>::type;
0067 
0068     // handles the member pointer rules of INVOKE
0069     template<typename Base, typename T,
0070              typename IsBaseOf = std::is_base_of<Base, shallow_decay<T>>,
0071              typename IsSame = std::is_same<Base, shallow_decay<T>>>
0072     using generalize_if_dissimilar = typename std::conditional<
0073         IsBaseOf::value || IsSame::value, T, generalize<T>>::type;
0074 
0075     template<typename Traits, bool = Traits::is_const_member::value
0076         || Traits::is_volatile_member::value
0077         || Traits::is_lvalue_reference_member::value
0078         || Traits::is_rvalue_reference_member::value>
0079     struct test_invoke {
0080 
0081         template<typename... Rgs,
0082             typename U = typename Traits::type>
0083         auto operator()(int, Rgs&&... rgs) const ->
0084             success<decltype(std::declval<U>()(static_cast<Rgs&&>(rgs)...))>;
0085 
0086         auto operator()(long, ...) const -> substitution_failure;
0087     };
0088 
0089     template<typename F>
0090     struct test_invoke<function<F>, true /*abominable*/> {
0091         auto operator()(...) const -> substitution_failure;
0092     };
0093 
0094     template<typename Pmf, bool Ignored>
0095     struct test_invoke<pmf<Pmf>, Ignored> {
0096 
0097         using class_t = typename pmf<Pmf>::class_type;
0098 
0099        template<typename U, typename... Rgs,
0100             typename Obj = generalize_if_dissimilar<class_t, U&&>>
0101         auto operator()(int, U&& u, Rgs&&... rgs) const ->
0102             success<decltype((std::declval<Obj>().*std::declval<Pmf>())(static_cast<Rgs&&>(rgs)...))>;
0103 
0104         auto operator()(long, ...) const -> substitution_failure;
0105     };
0106 
0107     template<typename Pmd, bool Ignored>
0108     struct test_invoke<pmd<Pmd>, Ignored> {
0109 
0110         using class_t = typename pmd<Pmd>::class_type;
0111 
0112         template<typename U,
0113             typename Obj = generalize_if_dissimilar<class_t, U&&>>
0114         auto operator()(int, U&& u) const ->
0115             success<decltype(std::declval<Obj>().*std::declval<Pmd>())>;
0116 
0117         auto operator()(long, ...) const -> substitution_failure;
0118     };
0119 
0120     template<typename T, typename... Args>
0121     struct is_invocable_impl {
0122         using traits = detail::traits<T>;
0123         using test = detail::test_invoke<traits>;
0124         using result = decltype(test{}(0, ::std::declval<Args>()...));
0125         using type = std::integral_constant<bool, result::value>;
0126     };
0127 
0128     template<typename... Args>
0129     struct is_invocable_impl<void, Args...> {
0130         using type = std::false_type;
0131     };
0132 
0133     template<typename IsInvocable, typename Ret, typename T, typename... Args>
0134     struct is_invocable_r_impl {
0135         using traits = detail::traits<T>;
0136         using test = detail::test_invoke<traits>;
0137         using result = decltype(test{}(0, ::std::declval<Args>()...));
0138         using type = std::integral_constant<bool,
0139             std::is_convertible<typename result::_::type, Ret>::value
0140                 || std::is_same<Ret, void>::value>;
0141     };
0142 
0143     template<typename Ret, typename T, typename... Args>
0144     struct is_invocable_r_impl<std::false_type, Ret, T, Args...> {
0145         using type = std::false_type;
0146     };
0147 
0148 }}} // namespace boost::callable_traits::detail
0149 
0150 #endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP