• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*=============================================================================
2    Copyright (c) 2014 Paul Fultz II
3    function.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_FUNCTION_H
9#define BOOST_HOF_GUARD_FUNCTION_FUNCTION_H
10
11/// BOOST_HOF_STATIC_FUNCTION
12/// ===================
13///
14/// Description
15/// -----------
16///
17
18/// The `BOOST_HOF_STATIC_FUNCTION` macro allows initializing a function object from a
19/// `constexpr` expression. It uses the best practices as outlined in
20/// [N4381](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html).
21/// This includes using `const` to avoid global state, compile-time
22/// initialization of the function object to avoid the [static initialization
23/// order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order), and an
24/// external address of the function object that is the same across translation
25/// units to avoid possible One-Definition-Rule(ODR) violations.
26///
27/// In C++17, this achieved using the `inline` keyword. However, on older
28/// compilers it is initialized using a reference to a static member variable.
29/// The static member variable is default constructed, as such the user variable
30/// is always default constructed regardless of the expression.
31///
32/// By default, all functions defined with `BOOST_HOF_STATIC_FUNCTION` use the
33/// [`boost::hof::reveal`](/include/boost/hof/reveal) adaptor to improve error messages.
34///
35/// Example
36/// -------
37///
38///     #include <boost/hof.hpp>
39///     #include <cassert>
40///
41///     struct sum_f
42///     {
43///         template<class T, class U>
44///         T operator()(T x, U y) const
45///         {
46///             return x+y;
47///         }
48///     };
49///
50///     BOOST_HOF_STATIC_FUNCTION(sum) = sum_f();
51///     BOOST_HOF_STATIC_FUNCTION(partial_sum) = boost::hof::partial(sum_f());
52///
53///     int main() {
54///         assert(sum(1, 2) == partial_sum(1)(2));
55///     }
56///
57
58#include <boost/hof/reveal.hpp>
59#if !BOOST_HOF_HAS_INLINE_VARIABLES
60#include <boost/hof/detail/static_const_var.hpp>
61#include <boost/hof/detail/constexpr_deduce.hpp>
62#endif
63
64namespace boost { namespace hof {
65
66namespace detail {
67
68struct reveal_static_const_factory
69{
70    constexpr reveal_static_const_factory()
71    {}
72    template<class F>
73    constexpr reveal_adaptor<F> operator=(const F& f) const
74    {
75#if BOOST_HOF_HAS_INLINE_VARIABLES
76#else
77        static_assert(BOOST_HOF_IS_DEFAULT_CONSTRUCTIBLE(F), "Static functions must be default constructible");
78#endif
79        return reveal_adaptor<F>(f);
80    }
81};
82}}} // namespace boost::hof
83
84#if BOOST_HOF_HAS_INLINE_VARIABLES
85#define BOOST_HOF_STATIC_FUNCTION(name) inline const constexpr auto name = boost::hof::detail::reveal_static_const_factory()
86#else
87#define BOOST_HOF_STATIC_FUNCTION(name) BOOST_HOF_STATIC_CONST_VAR(name) = BOOST_HOF_DETAIL_MSVC_CONSTEXPR_DEDUCE boost::hof::detail::reveal_static_const_factory()
88#endif
89
90#endif
91