is_callable.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright (c) 2009-2020 Vladimir Batov.
  2. // Use, modification and distribution are subject to the Boost Software License,
  3. // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
  4. #ifndef BOOST_CONVERT_IS_CALLABLE_HPP
  5. #define BOOST_CONVERT_IS_CALLABLE_HPP
  6. #include <boost/convert/detail/has_member.hpp>
  7. namespace boost { namespace cnv { namespace detail
  8. {
  9. using yes_type = ::boost::type_traits::yes_type;
  10. using no_type = ::boost::type_traits:: no_type;
  11. struct not_found {};
  12. struct void_return_substitute {};
  13. // The overloaded comma operator only kicks in for U != void essentially short-circuiting
  14. // itself ineffective. Otherwise, when U=void, the standard op,() kicks in and returns
  15. // 'void_return_substitute'.
  16. template<typename U> U const& operator, (U const&, void_return_substitute);
  17. template<typename U> U& operator, (U&, void_return_substitute);
  18. template <typename src, typename dst> struct match_const { typedef dst type; };
  19. template <typename src, typename dst> struct match_const<src const, dst> { typedef dst const type; };
  20. template<typename T, typename return_type>
  21. struct redirect
  22. {
  23. static no_type test (...);
  24. static yes_type test (return_type);
  25. };
  26. template<typename T>
  27. struct redirect<T, void>
  28. {
  29. static yes_type test (...);
  30. static no_type test (not_found);
  31. };
  32. }}}
  33. // No-args case needs to be implemented differently and has not been implemented yet.
  34. // template <typename R>
  35. // struct check<true, R ()>
  36. // C1. Need to find some unique/ugly names so that they do not clash if this macro is
  37. // used inside some other template class;
  38. // C2. Body of the function is not actually used anywhere.
  39. // However, Intel C++ compiler treats it as an error. So, we provide the body.
  40. #define BOOST_DECLARE_IS_CALLABLE(__trait_name__, __member_name__) \
  41. \
  42. template <typename __boost_is_callable_T__, typename __boost_is_callable_signature__> \
  43. class __trait_name__ \
  44. { \
  45. typedef __boost_is_callable_T__ class_type; /*C1*/ \
  46. typedef __boost_is_callable_signature__ signature; /*C1*/ \
  47. typedef boost::cnv::detail::not_found not_found; \
  48. \
  49. BOOST_DECLARE_HAS_MEMBER(has_member, __member_name__); \
  50. \
  51. struct mixin : public class_type \
  52. { \
  53. using class_type::__member_name__; \
  54. not_found __member_name__(...) const { return not_found(); /*C2*/} \
  55. }; \
  56. \
  57. typedef typename boost::cnv::detail::match_const<class_type, mixin>::type* mixin_ptr; \
  58. \
  59. template <bool has, typename F> struct check { static bool const value = false; }; \
  60. \
  61. template <typename Arg1, typename R> \
  62. struct check<true, R (Arg1)> \
  63. { \
  64. typedef typename boost::decay<Arg1>::type* a1; \
  65. \
  66. static bool const value = sizeof(boost::type_traits::yes_type) \
  67. == sizeof(boost::cnv::detail::redirect<class_type, R>::test( \
  68. (mixin_ptr(0)->__member_name__(*a1(0)), \
  69. boost::cnv::detail::void_return_substitute()))); \
  70. }; \
  71. template <typename Arg1, typename Arg2, typename R> \
  72. struct check<true, R (Arg1, Arg2)> \
  73. { \
  74. typedef typename boost::decay<Arg1>::type* a1; \
  75. typedef typename boost::decay<Arg2>::type* a2; \
  76. \
  77. static bool const value = sizeof(boost::type_traits::yes_type) \
  78. == sizeof(boost::cnv::detail::redirect<class_type, R>::test( \
  79. (mixin_ptr(0)->__member_name__(*a1(0), *a2(0)), \
  80. boost::cnv::detail::void_return_substitute()))); \
  81. }; \
  82. \
  83. public: \
  84. \
  85. /* Check the existence of __member_name__ first, then the signature. */ \
  86. static bool const value = check<has_member<class_type>::value, signature>::value; \
  87. }
  88. #endif // BOOST_CONVERT_IS_CALLABLE_HPP