Qt client - fixed downcast of XXX which does not point to an object of type chat_listener
[freeciv.git] / client / gui-qt / listener.h
bloba1e5302f13d07d82bbd00db0ba5cd0583073fd47
1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11 ***********************************************************************/
13 #ifndef FC__LISTENER_H
14 #define FC__LISTENER_H
16 #include <set>
18 /***************************************************************************
19 Helper template to connect C and C++ code.
21 This class is a helper to create Java-like "listeners" for "events"
22 generated in C code. If the C interface defines a callback foo() and
23 you want to use it as an event, you first declare a C++ interface:
25 ~~~~~{.cpp}
26 class foo_listener : public listener<foo_listener>
28 public:
29 virtual void foo() = 0;
31 ~~~~~
33 The listener needs some static data. Declaring it is as simple as putting
34 a macro in some source file:
36 ~~~~~{.cpp}
37 FC_CPP_DECLARE_LISTENER(foo_listener)
38 ~~~~~
40 Then, you call the listeners from the implementation of the C interface:
42 ~~~~~{.cpp}
43 void foo()
45 foo_listener::invoke(&foo_listener::foo);
47 ~~~~~
49 This will invoke foo() on all foo_listener objects.
51 == Listening to events
53 Listening to events is done by inheriting from a listener. When your
54 object is ready to receive events, it should call the listener's @c listen
55 function. This will typically be done in the constructor:
57 ~~~~~{.cpp}
58 class bar : private foo_listener
60 public:
61 explicit bar();
62 void foo();
65 bar::bar()
67 // Initialize the object here
68 foo_listener::listen();
70 ~~~~~
72 == Passing arguments
74 Passing arguments to the listeners is very simple: you write them after
75 the function pointer. For instance, let's say foo() takes an int. It can
76 be passed to the listeners as follows:
78 ~~~~~{.cpp}
79 void foo(int argument)
81 foo_listener::invoke(&foo_listener::foo, argument);
83 ~~~~~
85 As there may be an arbitrary number of listeners, passing mutable data
86 through invoke() is discouraged.
88 == Technical details
90 This class achieves its purpose using the Curiously Recurring Template
91 Pattern, hence the weird parent for listeners:
93 ~~~~~{.cpp}
94 class foo_listener : public listener<foo_listener>
95 ~~~~~
97 The template argument is used to specialize object storage and member
98 function invocation. Compilers should be able to inline calls to invoke(),
99 leaving only the overhead of looping on all instances.
101 @warning Implementation is not thread-safe.
102 ***************************************************************************/
103 template<class _type_>
104 class listener
106 public:
107 // The type a given specialization supports.
108 typedef _type_ type_t;
110 private:
111 // All instances of type_t that have called listen().
112 static std::set<type_t *> instances;
114 protected:
115 explicit listener();
116 virtual ~listener();
118 void listen();
120 public:
121 template<class _member_fct_>
122 static void invoke(_member_fct_ function);
124 template<class _member_fct_, class _arg1_t_>
125 static void invoke(_member_fct_ function, _arg1_t_ arg);
127 template<class _member_fct_, class _arg1_t_, class _arg2_t_>
128 static void invoke(_member_fct_ function, _arg1_t_ arg1, _arg2_t_ arg2);
131 /***************************************************************************
132 Macro to declare the static data needed by listener<> classes
133 ***************************************************************************/
134 #define FC_CPP_DECLARE_LISTENER(_type_) \
135 template<> \
136 std::set<_type_ *> listener<_type_>::instances = std::set<_type_ *>();
138 /***************************************************************************
139 Constructor
140 ***************************************************************************/
141 template<class _type_>
142 listener<_type_>::listener()
145 /***************************************************************************
146 Starts listening to events
147 ***************************************************************************/
148 template<class _type_>
149 void listener<_type_>::listen()
151 // If you get an error here, your listener likely doesn't inherit from the
152 // listener<> correctly. See the class documentation.
153 instances.insert(static_cast<type_t *>(this));
156 /***************************************************************************
157 Destructor
158 ***************************************************************************/
159 template<class _type_>
160 listener<_type_>::~listener()
162 instances.erase(reinterpret_cast<type_t *>(this));
165 /***************************************************************************
166 Invokes a member function on all instances of an listener type. Template
167 parameters are meant to be automatically deduced.
169 Zero-parameter overload.
171 @param function The member function to call
172 ***************************************************************************/
173 template<class _type_>
174 template<class _member_fct_>
175 void listener<_type_>::invoke(_member_fct_ function)
177 typename std::set<type_t *>::iterator it = instances.begin();
178 typename std::set<type_t *>::iterator end = instances.end();
179 for ( ; it != end; ++it) {
180 ((*it)->*function)();
184 /***************************************************************************
185 Invokes a member function on all instances of an listener type. Template
186 parameters are meant to be automatically deduced.
188 One-parameter overload.
190 @param function The member function to call
191 @param arg The argument to call the function with
192 ***************************************************************************/
193 template<class _type_>
194 template<class _member_fct_, class _arg1_t_>
195 void listener<_type_>::invoke(_member_fct_ function, _arg1_t_ arg)
197 typename std::set<type_t *>::iterator it = instances.begin();
198 typename std::set<type_t *>::iterator end = instances.end();
199 for ( ; it != end; ++it) {
200 ((*it)->*function)(arg);
204 /***************************************************************************
205 Invokes a member function on all instances of an listener type. Template
206 parameters are meant to be automatically deduced.
208 Two-parameters overload.
210 @param function The member function to call
211 @param arg1 The first argument to pass to the function
212 @param arg2 The second argument to pass to the function
213 ***************************************************************************/
214 template<class _type_>
215 template<class _member_fct_, class _arg1_t_, class _arg2_t_>
216 void listener<_type_>::invoke(_member_fct_ function,
217 _arg1_t_ arg1, _arg2_t_ arg2)
219 typename std::set<type_t *>::iterator it = instances.begin();
220 typename std::set<type_t *>::iterator end = instances.end();
221 for ( ; it != end; ++it) {
222 ((*it)->*function)(arg1, arg2);
226 #endif // FC__LISTENER_H