1 // Slot.hh for FbTk, Fluxbox Toolkit
2 // Copyright (c) 2008 Henrik Kinnunen (fluxgen at fluxbox dot org)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21 
22 #ifndef FBTK_SLOT_HH
23 #define FBTK_SLOT_HH
24 
25 #include "NotCopyable.hh"
26 
27 namespace FbTk {
28 
29 /// \namespace Implementation details for signals, do not use anything in this namespace
30 namespace SigImpl {
31 
32 struct EmptyArg {};
33 
34 /** A base class for all slots. It's purpose is to provide a virtual destructor and to enable the
35  * Signal class to hold a pointer to a generic slot.
36  */
37 class SlotBase: private FbTk::NotCopyable {
38 public:
~SlotBase()39     virtual ~SlotBase() {}
40 };
41 
42 } // namespace SigImpl
43 
44 /** Declares a pure virtual function call operator with a specific number of arguments (depending
45  * on the template specialization). This allows us to "call" any functor in an opaque way.
46  */
47 template<typename ReturnType, typename Arg1 = SigImpl::EmptyArg,
48          typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg>
49 class Slot: public SigImpl::SlotBase {
50 public:
51     virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0;
52 };
53 
54 /// Specialization for two arguments
55 template<typename ReturnType, typename Arg1, typename Arg2>
56 class Slot<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SlotBase {
57 public:
58     virtual ReturnType operator()(Arg1, Arg2) = 0;
59 };
60 
61 /// Specialization for one argument
62 template<typename ReturnType, typename Arg1>
63 class Slot<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase {
64 public:
65     virtual ReturnType operator()(Arg1) = 0;
66 };
67 
68 /// Specialization for no arguments
69 template<typename ReturnType>
70 class Slot<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase {
71 public:
72     virtual ReturnType operator()() = 0;
73 };
74 
75 /** A class which knows how to call a specific functor. It inherits from Slot and implemetents
76  * the function call operator
77  */
78 template<typename Functor, typename ReturnType, typename Arg1 = SigImpl::EmptyArg,
79          typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg>
80 class SlotImpl: public Slot<ReturnType, Arg1, Arg2, Arg3> {
81 public:
operator ()(Arg1 arg1,Arg2 arg2,Arg3 arg3)82     virtual ReturnType operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3)
83     { return static_cast<ReturnType>(m_functor(arg1, arg2, arg3)); }
84 
SlotImpl(Functor functor)85     SlotImpl(Functor functor) : m_functor(functor) {}
86 
87 private:
88     Functor m_functor;
89 };
90 
91 /// Specialization for two arguments
92 template<typename Functor, typename ReturnType, typename Arg1, typename Arg2>
93 class SlotImpl<Functor, ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1, Arg2> {
94 public:
operator ()(Arg1 arg1,Arg2 arg2)95     virtual ReturnType operator()(Arg1 arg1, Arg2 arg2)
96     { return static_cast<ReturnType>(m_functor(arg1, arg2)); }
97 
SlotImpl(Functor functor)98     SlotImpl(Functor functor) : m_functor(functor) {}
99 
100 private:
101     Functor m_functor;
102 };
103 
104 /// Specialization for one argument
105 template<typename Functor, typename ReturnType, typename Arg1>
106 class SlotImpl<Functor, ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1> {
107 public:
operator ()(Arg1 arg1)108     virtual ReturnType operator()(Arg1 arg1) { return static_cast<ReturnType>(m_functor(arg1)); }
109 
SlotImpl(Functor functor)110     SlotImpl(Functor functor) : m_functor(functor) {}
111 
112 private:
113     Functor m_functor;
114 };
115 
116 /// Specialization for no arguments
117 template<typename Functor, typename ReturnType>
118 class SlotImpl<Functor, ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType> {
119 public:
operator ()()120     virtual ReturnType operator()() { return static_cast<ReturnType>(m_functor()); }
121 
SlotImpl(Functor functor)122     SlotImpl(Functor functor) : m_functor(functor) {}
123 
124 private:
125     Functor m_functor;
126 };
127 
128 } // namespace FbTk
129 
130 #endif // FBTK_SLOT_H
131