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