1 /*============================================================================= 2 Copyright (c) 2014 Paul Fultz II 3 always.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_ALWAYS_H 9 #define BOOST_HOF_GUARD_FUNCTION_ALWAYS_H 10 11 #include <boost/hof/detail/delegate.hpp> 12 #include <boost/hof/detail/unwrap.hpp> 13 #include <boost/hof/detail/static_const_var.hpp> 14 15 /// always 16 /// ====== 17 /// 18 /// Description 19 /// ----------- 20 /// 21 /// The `always` function returns a function object that will always return 22 /// the value given to it, no matter what parameters are passed to the 23 /// function object. The nullary version(i.e. `always(void)`) will return 24 /// `void`. On compilers, that don't support constexpr functions returning 25 /// `void`, a private empty type is returned instead. This return type is 26 /// specified as `BOOST_HOF_ALWAYS_VOID_RETURN`. 27 /// 28 /// Synopsis 29 /// -------- 30 /// 31 /// template<class T> 32 /// constexpr auto always(T value); 33 /// 34 /// template<class T> 35 /// constexpr auto always(void); 36 /// 37 /// 38 /// Semantics 39 /// --------- 40 /// 41 /// assert(always(x)(xs...) == x); 42 /// 43 /// Requirements 44 /// ------------ 45 /// 46 /// T must be: 47 /// 48 /// * CopyConstructible 49 /// 50 /// Example 51 /// ------- 52 /// 53 /// #include <boost/hof.hpp> 54 /// #include <algorithm> 55 /// #include <cassert> 56 /// using namespace boost::hof; 57 /// 58 /// int main() { 59 /// int ten = 10; 60 /// assert( always(ten)(1,2,3,4,5) == 10 ); 61 /// } 62 /// 63 /// // Count all 64 /// template<class Iterator, class T> 65 /// auto count(Iterator first, Iterator last) 66 /// { 67 /// return std::count_if(first, last, always(true)); 68 /// } 69 /// 70 71 72 #ifndef BOOST_HOF_NO_CONSTEXPR_VOID 73 #if defined(__clang__) && BOOST_HOF_HAS_RELAXED_CONSTEXPR 74 #define BOOST_HOF_NO_CONSTEXPR_VOID 0 75 #else 76 #define BOOST_HOF_NO_CONSTEXPR_VOID 1 77 #endif 78 #endif 79 80 namespace boost { namespace hof { namespace always_detail { 81 82 template<class T, class=void> 83 struct always_base 84 { 85 T x; 86 87 BOOST_HOF_DELEGATE_CONSTRUCTOR(always_base, T, x) 88 89 typedef typename detail::unwrap_reference<T>::type result_type; 90 91 template<class... As> 92 constexpr result_type operator ()boost::hof::always_detail::always_base93 operator()(As&&...) const 94 noexcept(std::is_reference<result_type>::value || BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(result_type)) 95 { 96 return this->x; 97 } 98 }; 99 100 template<class T> 101 struct always_base<T, typename std::enable_if<!BOOST_HOF_IS_EMPTY(T)>::type> 102 { 103 T x; 104 always_baseboost::hof::always_detail::always_base105 constexpr always_base(T xp) noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T)) 106 : x(xp) 107 {} 108 109 typedef typename detail::unwrap_reference<T>::type result_type; 110 111 template<class... As> 112 constexpr result_type operator ()boost::hof::always_detail::always_base113 operator()(As&&...) const 114 noexcept(std::is_reference<result_type>::value || BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(result_type)) 115 { 116 return this->x; 117 } 118 }; 119 120 #if BOOST_HOF_NO_CONSTEXPR_VOID 121 #define BOOST_HOF_ALWAYS_VOID_RETURN boost::hof::always_detail::always_base<void>::void_ 122 #else 123 #define BOOST_HOF_ALWAYS_VOID_RETURN void 124 #endif 125 126 template<> 127 struct always_base<void> 128 { 129 always_baseboost::hof::always_detail::always_base130 constexpr always_base() noexcept 131 {} 132 133 struct void_ {}; 134 135 template<class... As> 136 constexpr BOOST_HOF_ALWAYS_VOID_RETURN operator ()boost::hof::always_detail::always_base137 operator()(As&&...) const noexcept 138 { 139 #if BOOST_HOF_NO_CONSTEXPR_VOID 140 return void_(); 141 #endif 142 } 143 }; 144 145 struct always_f 146 { 147 template<class T> operator ()boost::hof::always_detail::always_f148 constexpr always_detail::always_base<T> operator()(T x) const noexcept(BOOST_HOF_IS_NOTHROW_COPY_CONSTRUCTIBLE(T)) 149 { 150 return always_detail::always_base<T>(x); 151 } 152 operator ()boost::hof::always_detail::always_f153 constexpr always_detail::always_base<void> operator()() const noexcept 154 { 155 return always_detail::always_base<void>(); 156 } 157 }; 158 159 struct always_ref_f 160 { 161 template<class T> operator ()boost::hof::always_detail::always_ref_f162 constexpr always_detail::always_base<T&> operator()(T& x) const noexcept 163 { 164 return always_detail::always_base<T&>(x); 165 } 166 }; 167 168 } 169 BOOST_HOF_DECLARE_STATIC_VAR(always, always_detail::always_f); 170 BOOST_HOF_DECLARE_STATIC_VAR(always_ref, always_detail::always_ref_f); 171 172 }} // namespace boost::hof 173 174 #endif 175