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 80namespace boost { namespace hof { namespace always_detail { 81 82template<class T, class=void> 83struct 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 93 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 100template<class T> 101struct always_base<T, typename std::enable_if<!BOOST_HOF_IS_EMPTY(T)>::type> 102{ 103 T x; 104 105 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 113 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 126template<> 127struct always_base<void> 128{ 129 130 constexpr always_base() noexcept 131 {} 132 133 struct void_ {}; 134 135 template<class... As> 136 constexpr BOOST_HOF_ALWAYS_VOID_RETURN 137 operator()(As&&...) const noexcept 138 { 139#if BOOST_HOF_NO_CONSTEXPR_VOID 140 return void_(); 141#endif 142 } 143}; 144 145struct always_f 146{ 147 template<class T> 148 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 153 constexpr always_detail::always_base<void> operator()() const noexcept 154 { 155 return always_detail::always_base<void>(); 156 } 157}; 158 159struct always_ref_f 160{ 161 template<class T> 162 constexpr always_detail::always_base<T&> operator()(T& x) const noexcept 163 { 164 return always_detail::always_base<T&>(x); 165 } 166}; 167 168} 169BOOST_HOF_DECLARE_STATIC_VAR(always, always_detail::always_f); 170BOOST_HOF_DECLARE_STATIC_VAR(always_ref, always_detail::always_ref_f); 171 172}} // namespace boost::hof 173 174#endif 175