is_likely_lambda.hpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* Copyright 2017 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_TT_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP
  9. #define BOOST_TT_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/type_traits/detail/config.hpp>
  14. #include <boost/type_traits/integral_constant.hpp>
  15. #if defined(BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION)
  16. //
  17. // We don't need or use this, just define a dummy class:
  18. //
  19. namespace boost{ namespace type_traits_detail{
  20. template<typename T>
  21. struct is_likely_stateless_lambda : public false_type {};
  22. }}
  23. #elif !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !BOOST_WORKAROUND(BOOST_MSVC, < 1900)\
  24. && !(BOOST_WORKAROUND(BOOST_MSVC, == 1900) && defined(__CLR_VER))
  25. #include <boost/type_traits/is_convertible.hpp>
  26. #include <boost/type_traits/enable_if.hpp>
  27. namespace boost{
  28. namespace type_traits_detail{
  29. /* Stateless lambda expressions have one (and only one) call operator and are
  30. * convertible to a function pointer with the same signature. Non-lambda types
  31. * could satisfy this too, hence the "likely" qualifier.
  32. */
  33. template<typename T>
  34. struct has_one_operator_call_helper
  35. {
  36. template<typename Q> static boost::true_type test(decltype(&Q::operator())*);
  37. template<typename> static boost::false_type test(...);
  38. using type=decltype(test<T>(nullptr));
  39. };
  40. template<typename T>
  41. using has_one_operator_call=typename has_one_operator_call_helper<T>::type;
  42. template<typename T>
  43. struct equivalent_function_pointer
  44. {
  45. template<typename Q,typename R,typename... Args>
  46. static auto helper(R (Q::*)(Args...)const)->R(*)(Args...);
  47. template<typename Q,typename R,typename... Args>
  48. static auto helper(R (Q::*)(Args...))->R(*)(Args...);
  49. using type=decltype(helper(&T::operator()));
  50. };
  51. template<typename T,typename=void>
  52. struct is_likely_stateless_lambda : false_type{};
  53. template<typename T>
  54. struct is_likely_stateless_lambda<
  55. T,
  56. typename boost::enable_if_<has_one_operator_call<T>::value>::type> :
  57. boost::is_convertible<T, typename equivalent_function_pointer<T>::type
  58. >{};
  59. } /* namespace type_traits_detail */
  60. } /* namespace boost */
  61. #else
  62. //
  63. // Can't implement this:
  64. //
  65. namespace boost {
  66. namespace type_traits_detail {
  67. template<typename T>
  68. struct is_likely_stateless_lambda : public boost::integral_constant<bool, false> {};
  69. }}
  70. #endif
  71. #endif