SlotBind.h
1 /*
2  Copyright (C) 2008 Marc Boris Duerner
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  As a special exception, you may use this file as part of a free
10  software library without restriction. Specifically, if other files
11  instantiate templates or use macros or inline functions from this
12  file, or you compile this file and link it with other files to
13  produce an executable, this file does not by itself cause the
14  resulting executable to be covered by the GNU General Public
15  License. This exception does not however invalidate any other
16  reasons why the executable file might be covered by the GNU Library
17  General Public License.
18 
19  This library is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  Lesser General Public License for more details.
23 
24  You should have received a copy of the GNU Lesser General Public
25  License along with this library; if not, write to the:
26  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27  Boston, MA 02110-1301 USA
28 */
29 
30 #ifndef Pt_SlotBind_h
31 #define Pt_SlotBind_h
32 
33 #include <Pt/Api.h>
34 #include <Pt/Void.h>
35 #include <Pt/Callable.h>
36 #include <tuple>
37 #include <type_traits>
38 #include <utility>
39 
40 namespace Pt {
41 
42 template <typename T>
43 class BindAdaptorBase
44 {
45  public:
46  BindAdaptorBase(const Slot& s, const T& a)
47  : _slot( s.clone() )
48  , _a(a)
49  { }
50 
51  BindAdaptorBase(const BindAdaptorBase& c)
52  : _slot( c._slot->clone() )
53  , _a(c._a)
54  { }
55 
56  ~BindAdaptorBase()
57  { delete _slot; }
58 
59  BindAdaptorBase& operator=(const BindAdaptorBase& b)
60  {
61  if(this == &b)
62  return *this;
63 
64  Slot* s = b.slot().clone();
65  delete _slot;
66  _slot = s;
67 
68  _a = b._a;
69  return *this;
70  }
71 
72  Slot& slot()
73  {
74  return *_slot;
75  }
76 
77  const Slot& slot() const
78  {
79  return *_slot;
80  }
81 
82  const T& arg() const
83  {
84  return _a;
85  }
86 
87  private:
88  Slot* _slot;
89  T _a;
90 };
91 
92 namespace SigSlotDetail {
93 
94 template <typename R, typename Tuple, typename Indices>
95 class BindAdaptor;
96 
97 template <typename R, typename Tuple, std::size_t... Is>
98 class BindAdaptor<R, Tuple, std::index_sequence<Is...>>
99 : public Callable<R, typename std::tuple_element<Is, Tuple>::type...>
100 , public BindAdaptorBase<
101  typename std::tuple_element<std::tuple_size<Tuple>::value - 1, Tuple>::type>
102 {
103  public:
104  typedef typename std::tuple_element<std::tuple_size<Tuple>::value - 1, Tuple>::type BoundT;
105  typedef BasicSlot<R, typename std::tuple_element<Is, Tuple>::type...> SlotBase;
106  typedef BasicSlot<R, typename std::tuple_element<Is, Tuple>::type..., BoundT> FullSlotBase;
107  typedef Callable<R, typename std::tuple_element<Is, Tuple>::type...> CallableBase;
108  typedef Callable<R, typename std::tuple_element<Is, Tuple>::type..., BoundT> FullCallable;
109 
110  public:
111  BindAdaptor(const FullSlotBase& slot, const BoundT& arg)
112  : BindAdaptorBase<BoundT>(slot, arg)
113  { }
114 
115  CallableBase* clone() const
116  {
117  return new BindAdaptor(*this);
118  }
119 
120  // inherit doc
121  R call(typename std::tuple_element<Is, Tuple>::type... args) const
122  {
123  const FullCallable* callable =
124  static_cast<const FullCallable*>( this->slot().callable() );
125  return callable->call(args..., this->arg());
126  }
127 
128  // inherit doc
129  void invoke(typename std::tuple_element<Is, Tuple>::type... args) const
130  {
131  const FullCallable* callable =
132  static_cast<const FullCallable*>( this->slot().callable() );
133  callable->call(args..., this->arg());
134  }
135 };
136 
137 } // namespace SigSlotDetail
138 
146 template <typename R, typename Tuple, typename Indices>
148 : public SigSlotDetail::BindAdaptor<R, Tuple, Indices>::SlotBase
149 {
150  typedef SigSlotDetail::BindAdaptor<R, Tuple, Indices> AdaptorT;
151 
152  public:
153  template <typename T>
154  BoundSlot(const typename AdaptorT::FullSlotBase& slot, const T& arg)
155  : _adaptor(slot, arg)
156  { }
157 
158  Slot* clone() const
159  {
160  return new BoundSlot(*this);
161  }
162 
163  // inherit doc
164  virtual const Callback* callable() const
165  {
166  return &_adaptor;
167  }
168 
169  virtual void onConnect(const Connection& connection)
170  {
171  _adaptor.slot().onConnect(connection);
172  }
173 
174  virtual void onDisconnect(const Connection& connection)
175  {
176  _adaptor.slot().onDisconnect(connection);
177  }
178 
179  virtual bool equals(const Slot& slot) const
180  {
181  return _adaptor.slot().equals(slot);
182  }
183 
184  private:
185  AdaptorT _adaptor;
186 };
187 
188 namespace SigSlotDetail {
189 
190 template <typename R, typename Tuple>
191 struct BoundSlotTraits;
192 
193 template <typename R, typename A, typename... As>
194 struct BoundSlotTraits<R, std::tuple<A, As...>>
195 {
196  typedef BoundSlot<R,
197  std::tuple<A, As...>,
198  std::make_index_sequence<sizeof...(As)>> Type;
199 };
200 
201 } // namespace SigSlotDetail
202 
210 template <typename R, typename... As, typename T>
211 typename SigSlotDetail::BoundSlotTraits<R, std::tuple<As...>>::Type
212 slot(const BasicSlot<R, As...>& slot, const T& arg)
213 {
214  typedef typename SigSlotDetail::BoundSlotTraits<R, std::tuple<As...>>::Type BoundSlotT;
215  return BoundSlotT(slot, arg);
216 }
217 
218 } // namespace Pt
219 
220 #endif
Core module.
Definition: Allocator.h:33
Slot produced by binding a final argument to another slot.
Definition: SlotBind.h:149
SigSlotDetail::BoundSlotTraits< R, std::tuple< As... > >::Type slot(const BasicSlot< R, As... > &slot, const T &arg)
Binds the final argument of a slot to a copied value.
Definition: SlotBind.h:212
Endpoint of a signal/slot connection.
Definition: Slot.h:55
Represents a connection between a Signal/Delegate and a slot.
Definition: Connection.h:96