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