The Battle for Wesnoth  1.13.4+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) 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 #ifndef INCL_FUNCTIONAL_HPP_
19 #define INCL_FUNCTIONAL_HPP_
20 
21 #include "global.hpp"
22 #include <functional>
23 #include <boost/bind.hpp> // Because std::bind is just not flexible enough
24 
25 // We'd like to just say "using namespace std::placeholders", but unfortunately
26 // that clashes with Boost.Bind's placeholders in some cases (even if bind.hpp is not included).
27 // Instead, we specialize std::is_placeholder for the Boost placeholders,
28 // so that Boost placeholders can be passed to std::bind.
29 
30 namespace std { // Some compilers can't handle it being specialized in the global scope
31  template<int N>
32  struct is_placeholder<boost::arg<N>> : public integral_constant<int, N> {};
33 }
34 
35 namespace detail {
36  template<typename Ret, typename... T>
37  struct apply {
38  using result_type = void;
39  apply(std::function<Ret(T...)> fcn) : 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(boost::bind(
97  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 boost::bind(detail::make_apply(std::function<T>(fcn)), bindings...);
103 }
104 
105 template<typename F, typename... P>
106 auto bind_void_exact(F fcn, P... bindings)
107 #ifndef HAVE_CXX14
108 -> decltype(
109  boost::bind(detail::make_apply(std::function<typename detail::function_base<F>::type>(fcn)), bindings...)
110 )
111 #endif
112 {
113  using T = typename detail::function_base<F>::type;
114  return std::bind(detail::make_apply(std::function<T>(fcn)), bindings...);
115 }
116 
117 /* A note on why std::bind is not flexible enough:
118 
119 1. The functions produced do not silently consume extra parameters passed to them.
120 This is not a bad thing per se, but some of Wesnoth's code relied on it.
121 It's useful behaviour, as well.
122 
123 2. A function that returns a value cannot be bound in a function type that returns void.
124 This is also relied upon in several places.
125 
126 If behaviour #1 is needed, we need to use boost::bind. For behaviour #2, this won't work;
127 instead, the bind_void function is provided. (This also provides behaviour #1.
128 To get #2 without #1, use bind_void_exact.)
129 */
130 
131 #endif
apply< Ret, T...> make_apply(std::function< Ret(T...)> fcn)
Definition: functional.hpp:48
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1806
std::function< Ret(T...)> fcn
Definition: functional.hpp:44
typename function_base< decltype(&F::operator())>::type type
Definition: functional.hpp:54
apply(std::function< Ret(T...)> fcn)
Definition: functional.hpp:39
STL namespace.
const GLfloat * params
Definition: glew.h:1499
auto bind_void(F fcn, P...bindings) -> decltype(boost::bind(detail::make_apply(std::function< typename detail::function_base< F >::type >(fcn)), bindings...))
Definition: functional.hpp:94
auto bind_void_exact(F fcn, P...bindings) -> decltype(boost::bind(detail::make_apply(std::function< typename detail::function_base< F >::type >(fcn)), bindings...))
Definition: functional.hpp:106
void operator()(T...params)
Definition: functional.hpp:40