• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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