can_be_called.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. can_be_called.h
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_HOF_GUARD_CAN_BE_CALLED_H
  8. #define BOOST_HOF_GUARD_CAN_BE_CALLED_H
  9. #include <boost/hof/config.hpp>
  10. #include <boost/hof/detail/and.hpp>
  11. #include <boost/hof/detail/holder.hpp>
  12. #include <boost/hof/detail/using.hpp>
  13. namespace boost { namespace hof { namespace detail {
  14. #if BOOST_HOF_NO_EXPRESSION_SFINAE
  15. struct dont_care
  16. {
  17. dont_care(...);
  18. };
  19. template<class T>
  20. struct never_care
  21. {
  22. typedef dont_care type;
  23. };
  24. struct cant_be_called_type
  25. {};
  26. struct no_type
  27. {};
  28. template<class F>
  29. struct is_callable_wrapper_fallback
  30. {
  31. template<class... Ts>
  32. auto operator()(Ts&&...) const
  33. -> decltype(std::declval<F>()(std::declval<Ts>()...));
  34. };
  35. template<class T, class U=typename std::remove_cv<typename std::remove_reference<T>::type>::type>
  36. struct is_callable_wrapper_base
  37. : std::conditional<BOOST_HOF_IS_CLASS(U) && !BOOST_HOF_IS_FINAL(U), U, is_callable_wrapper_fallback<U>>
  38. {};
  39. template<class F, class... Ts>
  40. struct is_callable_wrapper : is_callable_wrapper_base<F>::type
  41. {
  42. is_callable_wrapper();
  43. typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...);
  44. operator pointer_to_function() const;
  45. };
  46. template<class T>
  47. struct not_
  48. : std::integral_constant<bool, !T::value>
  49. {};
  50. template<class F, class... Ts>
  51. struct can_be_called
  52. : not_<std::is_same<cant_be_called_type, typename std::decay<decltype(
  53. is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...)
  54. )>::type>>
  55. {};
  56. template<class F, class... Ts>
  57. struct check_args;
  58. template<class Res, class... Ts, class... Us>
  59. struct check_args<Res(Us...), Ts...>
  60. : and_<std::is_convertible<Ts, Us>...>
  61. {};
  62. template<class Res, class... Ts, class... Us>
  63. struct can_be_called<Res(*)(Us...), Ts...>
  64. : std::conditional<sizeof...(Ts) == sizeof...(Us),
  65. check_args<Res(Us...), Ts...>,
  66. std::false_type
  67. >::type
  68. {};
  69. template<class Res, class... Ts, class... Us>
  70. struct can_be_called<Res(Us...), Ts...>
  71. : std::conditional<sizeof...(Ts) == sizeof...(Us),
  72. check_args<Res(Us...), Ts...>,
  73. std::false_type
  74. >::type
  75. {};
  76. #else
  77. template<class T>
  78. T&& called_val() noexcept;
  79. template<class... Ts>
  80. struct callable_args
  81. {};
  82. template<class F, class Args, class=void>
  83. struct can_be_called_impl
  84. : std::false_type
  85. {};
  86. template<class F, class... Args>
  87. struct can_be_called_impl<F, callable_args<Args...>, typename detail::holder<
  88. decltype( boost::hof::detail::called_val<F>()(boost::hof::detail::called_val<Args>()...) )
  89. >::type>
  90. : std::true_type
  91. {};
  92. template<class F, class... Ts>
  93. BOOST_HOF_USING(can_be_called, can_be_called_impl<F, detail::callable_args<Ts...>>);
  94. #endif
  95. }}} // namespace boost::hof
  96. #endif