The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
functional.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by the Battle for Wesnoth Project http://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12  */
13 
14 /*
15  * Wrapper header to allow use of placeholder variables without a namespace.
16  */
17 
18 #pragma once
19 
20 #include "global.hpp"
21 #include <functional>
22 #include <boost/bind.hpp>
23 
24 // We'd like to just say "using namespace std::placeholders", but unfortunately
25 // that clashes with Boost.Bind's placeholders in some cases (even if bind.hpp is not included).
26 // Instead, we specialize std::is_placeholder for the Boost placeholders,
27 // so that Boost placeholders can be passed to std::bind.
28 
29 namespace std { // Some compilers can't handle it being specialized in the global scope
30  template<int N>
31  struct is_placeholder<boost::arg<N>> : public integral_constant<int, N> {};
32 }
33 
34 namespace detail {
35  template<typename Ret, typename... T>
36  struct apply {
37  using result_type = void;
38  apply(const std::function<Ret(T...)>& fcn) : fcn(fcn) {}
39  apply(Ret(*fcn)(T...)) : fcn(fcn) {}
40  void operator()(T... params) {
41  fcn(std::forward<T>(params)...);
42  }
43  private:
44  std::function<Ret(T...)> fcn;
45  };
46 
47  template<typename Ret, typename... T>
48  apply<Ret, T...> make_apply(std::function<Ret(T...)> fcn) {
49  return apply<Ret, T...>(fcn);
50  }
51 
52  template<typename F>
53  struct function_base {
55  };
56 
57  template<typename Ret, typename... P>
58  struct function_base<Ret(P...)> {
59  typedef Ret type(P...);
60  };
61 
62  template<typename Ret, typename... P>
63  struct function_base<Ret(*)(P...)> {
64  typedef Ret type(P...);
65  };
66 
67  template<typename Ret, typename Class, typename... P>
68  struct function_base<Ret(Class::*)(P...)> {
69  typedef Ret type(Class,P...);
70  };
71 
72  template<typename Ret, typename Class, typename... P>
73  struct function_base<Ret(Class::*)(P...)const> {
74  typedef Ret type(const Class,P...);
75  };
76 
77  template<typename Ret, typename Class, typename... P>
78  struct function_base<Ret(Class::*)(P...)volatile > {
79  typedef Ret type(volatile Class,P...);
80  };
81 
82  template<typename Ret, typename Class, typename... P>
83  struct function_base<Ret(Class::*)(P...)const volatile> {
84  typedef Ret type(const volatile Class,P...);
85  };
86 
87  template<typename Ret, typename... P>
88  struct function_base<std::function<Ret(P...)>> {
89  typedef Ret type(P...);
90  };
91 }
92 
93 template<typename F, typename... P>
94 auto bind_void(F fcn, P... bindings)
95 #ifndef HAVE_CXX14
96 -> decltype(
97  std::bind(detail::make_apply(std::function<typename detail::function_base<F>::type>(fcn)), bindings...)
98 )
99 #endif
100 {
101  using T = typename detail::function_base<F>::type;
102  return std::bind(detail::make_apply(std::function<T>(fcn)), bindings...);
103 }
104 
105 /* A note on why std::bind is not flexible enough:
106 
107 1. The functions produced do not silently consume extra parameters passed to them.
108 This is not a bad thing per se, but some of Wesnoth's code relied on it.
109 It's useful behaviour, as well.
110 
111 2. A function that returns a value cannot be bound in a function type that returns void.
112 This is also relied upon in several places.
113 
114 If behaviour #1 is needed, we can use boost::bind, though a lambda with unused arguments may be better.
115 For behaviour #2, the bind_void function is provided.
116 */
apply< Ret, T...> make_apply(std::function< Ret(T...)> fcn)
Definition: functional.hpp:48
std::function< Ret(T...)> fcn
Definition: functional.hpp:44
apply(const std::function< Ret(T...)> &fcn)
Definition: functional.hpp:38
typename function_base< decltype(&F::operator())>::type type
Definition: functional.hpp:54
STL namespace.
apply(Ret(*fcn)(T...))
Definition: functional.hpp:39
auto bind_void(F fcn, P...bindings) -> decltype(std::bind(detail::make_apply(std::function< typename detail::function_base< F >::type >(fcn)), bindings...))
Definition: functional.hpp:94
void operator()(T...params)
Definition: functional.hpp:40