mp_defer.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED
  2. #define BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED
  3. // Copyright 2015-2020, 2023 Peter Dimov
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #include <boost/mp11/integral.hpp>
  7. #include <boost/mp11/detail/config.hpp>
  8. namespace boost
  9. {
  10. namespace mp11
  11. {
  12. // mp_if, mp_if_c
  13. namespace detail
  14. {
  15. template<bool C, class T, class... E> struct mp_if_c_impl
  16. {
  17. };
  18. template<class T, class... E> struct mp_if_c_impl<true, T, E...>
  19. {
  20. using type = T;
  21. };
  22. template<class T, class E> struct mp_if_c_impl<false, T, E>
  23. {
  24. using type = E;
  25. };
  26. } // namespace detail
  27. template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
  28. template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
  29. // mp_valid
  30. #if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800
  31. // contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17
  32. namespace detail
  33. {
  34. template<class...> using void_t = void;
  35. template<class, template<class...> class F, class... T>
  36. struct mp_valid_impl: mp_false {};
  37. template<template<class...> class F, class... T>
  38. struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {};
  39. } // namespace detail
  40. template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
  41. #else
  42. // implementation by Bruno Dutra (by the name is_evaluable)
  43. namespace detail
  44. {
  45. template<template<class...> class F, class... T> struct mp_valid_impl
  46. {
  47. template<template<class...> class G, class = G<T...>> static mp_true check(int);
  48. template<template<class...> class> static mp_false check(...);
  49. using type = decltype(check<F>(0));
  50. };
  51. } // namespace detail
  52. template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
  53. #endif
  54. template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
  55. // mp_defer
  56. namespace detail
  57. {
  58. template<template<class...> class F, class... T> struct mp_defer_impl
  59. {
  60. using type = F<T...>;
  61. };
  62. struct mp_no_type
  63. {
  64. };
  65. #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
  66. template<template<class...> class F, class... T> struct mp_defer_cuda_workaround
  67. {
  68. using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
  69. };
  70. #endif
  71. } // namespace detail
  72. #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
  73. template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type;
  74. #else
  75. template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
  76. #endif
  77. } // namespace mp11
  78. } // namespace boost
  79. #endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED