1 /*=============================================================================
2 Copyright (c) 2012 Paul Fultz II
3 delgate.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
8 #ifndef BOOST_HOF_GUARD_FUNCTION_DELGATE_H
9 #define BOOST_HOF_GUARD_FUNCTION_DELGATE_H
10
11 #include <type_traits>
12 #include <utility>
13 #include <boost/hof/config.hpp>
14 #include <boost/hof/detail/and.hpp>
15 #include <boost/hof/detail/holder.hpp>
16 #include <boost/hof/detail/forward.hpp>
17 #include <boost/hof/detail/using.hpp>
18 #include <boost/hof/detail/intrinsics.hpp>
19 #include <boost/hof/detail/noexcept.hpp>
20
21
22 #define BOOST_HOF_ENABLE_IF_CONVERTIBLE(...) \
23 class=typename std::enable_if<BOOST_HOF_IS_CONVERTIBLE(__VA_ARGS__)>::type
24
25 #define BOOST_HOF_ENABLE_IF_CONVERTIBLE_UNPACK(...) \
26 class=typename std::enable_if<BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_CONVERTIBLE(__VA_ARGS__))>::type
27
28 #define BOOST_HOF_ENABLE_IF_BASE_OF(...) \
29 class=typename std::enable_if<BOOST_HOF_IS_BASE_OF(__VA_ARGS__)>::type
30
31 #define BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(...) \
32 class=typename std::enable_if<BOOST_HOF_IS_CONSTRUCTIBLE(__VA_ARGS__)>::type
33
34 #define BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(...) \
35 BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(__VA_ARGS__))
36
37 #define BOOST_HOF_INHERIT_DEFAULT(C, ...) \
38 template<bool FitPrivateEnableBool_##__LINE__=true, \
39 class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && boost::hof::detail::is_default_constructible_c<__VA_ARGS__>()>::type> \
40 constexpr C() BOOST_HOF_NOEXCEPT(boost::hof::detail::is_nothrow_default_constructible_c<__VA_ARGS__>()) {}
41
42 #define BOOST_HOF_INHERIT_DEFAULT_EMPTY(C, ...) \
43 template<bool FitPrivateEnableBool_##__LINE__=true, \
44 class=typename std::enable_if<FitPrivateEnableBool_##__LINE__ && \
45 boost::hof::detail::is_default_constructible_c<__VA_ARGS__>() && BOOST_HOF_IS_EMPTY(__VA_ARGS__) \
46 >::type> \
47 constexpr C() BOOST_HOF_NOEXCEPT(boost::hof::detail::is_nothrow_default_constructible_c<__VA_ARGS__>()) {}
48
49 #if BOOST_HOF_NO_TYPE_PACK_EXPANSION_IN_TEMPLATE
50
51 #define BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr_, C, T, var) \
52 template<class... FitXs, typename boost::hof::detail::enable_if_constructible<C, T, FitXs...>::type = 0> \
53 constexpr_ C(FitXs&&... fit_xs) \
54 BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, FitXs&&...) \
55 : var((FitXs&&)boost::hof::forward<FitXs>(fit_xs)...) {}
56
57 #else
58 #define BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr_, C, T, var) \
59 template<class... FitXs, BOOST_HOF_ENABLE_IF_CONSTRUCTIBLE(T, FitXs&&...)> \
60 constexpr_ C(FitXs&&... fit_xs) \
61 BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(T, FitXs&&...) \
62 : var(BOOST_HOF_FORWARD(FitXs)(fit_xs)...) {}
63
64 #endif
65
66 #define BOOST_HOF_DELEGATE_CONSTRUCTOR(C, T, var) BOOST_HOF_DELGATE_PRIMITIVE_CONSTRUCTOR(constexpr, C, T, var)
67
68 // Currently its faster to use `BOOST_HOF_DELEGATE_CONSTRUCTOR` than `using
69 // Base::Base;`
70 #if 1
71 #define BOOST_HOF_INHERIT_CONSTRUCTOR(Derived, Base) BOOST_HOF_DELEGATE_CONSTRUCTOR(Derived, Base, Base)
72 #else
73 #define BOOST_HOF_INHERIT_CONSTRUCTOR(Derived, Base) \
74 using fit_inherit_base = Base; \
75 using fit_inherit_base::fit_inherit_base; \
76 Derived()=default; \
77 template<class FitX, BOOST_HOF_ENABLE_IF_CONVERTIBLE(FitX, Base)> \
78 constexpr Derived(FitX&& fit_x) : Base(BOOST_HOF_FORWARD(FitX)(fit_x)) {}
79 #endif
80
81 namespace boost { namespace hof {
82 namespace detail {
83
84 template<class... Xs>
is_nothrow_default_constructible_c()85 constexpr bool is_nothrow_default_constructible_c()
86 {
87 return BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(Xs));
88 }
89
90 template<class... Xs>
is_default_constructible_c()91 constexpr bool is_default_constructible_c()
92 {
93 return BOOST_HOF_AND_UNPACK(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(Xs));
94 }
95
96 template<class... Xs>
97 BOOST_HOF_USING(is_default_constructible, std::integral_constant<bool, is_default_constructible_c<Xs...>()>);
98
99 template<class C, class X, class... Xs>
100 struct enable_if_constructible
101 : std::enable_if<is_constructible<X, Xs&&...>::value, int>
102 {};
103
104 }
105 }} // namespace boost::hof
106
107 #endif
108