summaryrefslogtreecommitdiff
path: root/sigc++/adaptors/retype.h
blob: ce2adcd1016164b341f6b4b6d6fe033a152a77b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Copyright 2003 - 2016, The libsigc++ Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef SIGC_ADAPTORS_RETYPE_H
#define SIGC_ADAPTORS_RETYPE_H

#include <sigc++/adaptors/adapts.h>
#include <sigc++/functors/ptr_fun.h>
#include <sigc++/functors/mem_fun.h>
#include <sigc++/functors/slot.h>

namespace sigc
{

/** @defgroup retype retype(), retype_return()
 * sigc::retype() alters a sigc::pointer_functor, a sigc::mem_functor or
 * a @ref sigc::slot<T_return(T_arg...)> "sigc::slot"
 * in that it makes C-style casts to the functor's parameter types
 * of all parameters passed through operator()().
 *
 * Use this adaptor for inline conversion between numeric or other simple types.
 * @par Example:
 * @code
 * void foo(int);
 * sigc::retype(sigc::ptr_fun(&foo))(5.7F); // calls foo(5)
 * @endcode
 *
 * The functor that sigc::retype() returns can be passed directly into
 * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()".
 *
 * @par Example:
 * @code
 * sigc::signal<void(float)> some_signal;
 * void foo(int);
 * some_signal.connect(sigc::retype(sigc::ptr_fun(&foo)));
 * @endcode
 *
 * This adaptor builds an exception in that it only works on sigc::pointer_functor,
 * sigc::mem_functor and @ref sigc::slot<T_return(T_arg...)> "sigc::slot"
 * because it needs sophisticated information about
 * the parameter types that cannot be deduced from arbitrary functor types.
 *
 * sigc::retype_return() alters the return type of an arbitrary functor.
 * Like in sigc::retype() a C-style cast is performed. Usage sigc::retype_return() is
 * not restricted to libsigc++ functor types but you need to
 * specify the new return type as a template parameter.
 *
 * @par Example:
 * @code
 * float foo();
 * std::cout << sigc::retype_return<int>(&foo)(); // converts foo's return value to an integer
 * @endcode
 *
 * @ingroup adaptors
 */

/** Adaptor that performs C-style casts on the parameters passed on to the functor.
 * Use the convenience function sigc::retype() to create an instance of retype_functor.
 *
 * The following template arguments are used:
 * - @e T_functor Type of the functor to wrap.
 * - @e T_type Types of @e T_functor's arguments.
 *
 * @ingroup retype
 */
template<typename T_functor, typename... T_type>
struct retype_functor : public adapts<T_functor>
{
  template<typename... T_arg>
  decltype(auto) operator()(T_arg... a)
  {
    return std::invoke(this->functor_, static_cast<T_type>(a)...);
  }

  /** Constructs a retype_functor object that performs C-style casts on the parameters passed on to
   * the functor.
   * @param functor Functor to invoke from operator()().
   */
  explicit retype_functor(type_trait_take_t<T_functor> functor) : adapts<T_functor>(functor) {}
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS
// template specialization of visitor<>::do_visit_each<>(action, functor):
/** Performs a functor on each of the targets of a functor.
 * The function overload for sigc::retype_functor performs a functor on the
 * functor stored in the sigc::retype_functor object.
 *
 * @ingroup retype
 */
template<typename T_functor, typename... T_type>
struct visitor<retype_functor<T_functor, T_type...>>
{
  template<typename T_action>
  static void do_visit_each(const T_action& action,
    const retype_functor<T_functor, T_type...>& target)
  {
    sigc::visit_each(action, target.functor_);
  }
};
#endif // DOXYGEN_SHOULD_SKIP_THIS

// This one takes, for instance, a mem_functor or bound_mem_functor:
/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters
 * passed on to the functor.
 *
 * @param functor Functor that should be wrapped.
 * @return Adaptor that executes @e functor performing C-style casts on the paramters passed on.
 *
 * @ingroup retype
 */
template<template<typename T_func, typename... T_arg> class T_functor,
  typename T_func,
  typename... T_arg>
inline decltype(auto)
retype(const T_functor<T_func, T_arg...>& functor)
{
  return retype_functor<T_functor<T_func, T_arg...>, T_arg...>(functor);
}

// This one takes, for instance, a pointer_functor or slot:
/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters
 * passed on to the functor.
 *
 * @param functor Functor that should be wrapped.
 * @return Adaptor that executes @e functor performing C-style casts on the paramters passed on.
 *
 * @ingroup retype
 */
template<template<typename T_return, typename... T_arg> class T_functor,
  typename T_return,
  typename... T_arg>
inline decltype(auto)
retype(const T_functor<T_return(T_arg...)>& functor)
{
  return retype_functor<T_functor<T_return(T_arg...)>, T_arg...>(functor);
}

} /* namespace sigc */

#endif /* SIGC_ADAPTORS_RETYPE_H */