diff options
author | Henrik Kinnunen <fluxgen@fluxbox.org> | 2010-03-19 01:23:41 (GMT) |
---|---|---|
committer | Henrik Kinnunen <fluxgen@fluxbox.org> | 2010-03-19 01:23:41 (GMT) |
commit | ceff86b79401c27ed83cad65f59a6621c9a58084 (patch) | |
tree | 3dc59ecc1a7a5b31b2d87686aacc3c6e2dbdc5ab | |
parent | 68e90ab84fc8720264694de47c1ac33c401b49e5 (diff) | |
download | fluxbox-ceff86b79401c27ed83cad65f59a6621c9a58084.zip fluxbox-ceff86b79401c27ed83cad65f59a6621c9a58084.tar.bz2 |
Added SelectArg and MemFunSelectArg*
The MemFunSelectArg* functions can be used to select
a specific argument from a signal. For example this would
select the string argument as argument to the callback:
Signal<void, int, float, string> signal;
signal.connect(MemFunSelectArg2(obj, &Object::takesOneStringArg));
signal.emit(10, 3.14, "hello");
...
void Object::takesOneStringArg(const string& value) {
...
}
-rw-r--r-- | src/FbTk/MemFun.hh | 56 | ||||
-rw-r--r-- | src/FbTk/STLUtil.hh | 19 | ||||
-rw-r--r-- | src/FbTk/SelectArg.hh | 74 | ||||
-rw-r--r-- | src/tests/testSignals.cc | 33 |
4 files changed, 181 insertions, 1 deletions
diff --git a/src/FbTk/MemFun.hh b/src/FbTk/MemFun.hh index 0425fc6..d265703 100644 --- a/src/FbTk/MemFun.hh +++ b/src/FbTk/MemFun.hh | |||
@@ -22,6 +22,8 @@ | |||
22 | #ifndef FBTK_MEM_FUN_HH | 22 | #ifndef FBTK_MEM_FUN_HH |
23 | #define FBTK_MEM_FUN_HH | 23 | #define FBTK_MEM_FUN_HH |
24 | 24 | ||
25 | #include "SelectArg.hh" | ||
26 | |||
25 | namespace FbTk { | 27 | namespace FbTk { |
26 | 28 | ||
27 | /// No argument functor | 29 | /// No argument functor |
@@ -218,6 +220,60 @@ MemFunIgnoreArgs( Object& obj, ReturnType (Object:: *action)(Arg1,Arg2) ) { | |||
218 | return MemFun2IgnoreArgs<ReturnType, Object, Arg1, Arg2>(obj, action); | 220 | return MemFun2IgnoreArgs<ReturnType, Object, Arg1, Arg2>(obj, action); |
219 | } | 221 | } |
220 | 222 | ||
223 | /** | ||
224 | * Creates a functor that selects a specific argument of three possible ones | ||
225 | * and uses it for the single argument operator. | ||
226 | */ | ||
227 | template < int ArgNum, typename Functor> | ||
228 | class MemFunSelectArgImpl { | ||
229 | public: | ||
230 | |||
231 | MemFunSelectArgImpl(Functor func): | ||
232 | m_func(func) { | ||
233 | } | ||
234 | |||
235 | template <typename Type1, typename Type2, typename Type3> | ||
236 | void operator ()(Type1 a, Type2 b, Type3 c) { | ||
237 | m_func(STLUtil::SelectArg<ArgNum>()(a, b, c)); | ||
238 | } | ||
239 | |||
240 | template <typename Type1, typename Type2> | ||
241 | void operator ()(Type1 a, Type2 b) { | ||
242 | m_func(STLUtil::SelectArg<ArgNum>()(a, b)); | ||
243 | } | ||
244 | |||
245 | template <typename Type1> | ||
246 | void operator ()(Type1 a) { | ||
247 | m_func(a); | ||
248 | } | ||
249 | |||
250 | private: | ||
251 | Functor m_func; | ||
252 | }; | ||
253 | |||
254 | /// Creates a functor that selects the first argument of three possible ones | ||
255 | /// and uses it for the single argument operator. | ||
256 | template <typename ReturnType, typename Object, typename Arg1> | ||
257 | MemFunSelectArgImpl<0, MemFun1<ReturnType, Object, Arg1> > | ||
258 | MemFunSelectArg0(Object& obj, ReturnType (Object:: *action)(Arg1)) { | ||
259 | return MemFunSelectArgImpl<0, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); | ||
260 | } | ||
261 | |||
262 | /// Creates a functor that selects the second argument (or first if there is | ||
263 | /// only one) of three possible onesand uses it for the single argument operator. | ||
264 | template <typename ReturnType, typename Object, typename Arg1> | ||
265 | MemFunSelectArgImpl<1, MemFun1<ReturnType, Object, Arg1> > | ||
266 | MemFunSelectArg1(Object& obj, ReturnType (Object:: *action)(Arg1)) { | ||
267 | return MemFunSelectArgImpl<1, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); | ||
268 | } | ||
269 | |||
270 | /// Creates a functor that selects the third argument (or the last argument if there is | ||
271 | /// less than three arguments) of three possible onesand uses it for the single argument operator. | ||
272 | template <typename ReturnType, typename Object, typename Arg1> | ||
273 | MemFunSelectArgImpl<2, MemFun1<ReturnType, Object, Arg1> > | ||
274 | MemFunSelectArg2(Object& obj, ReturnType (Object:: *action)(Arg1)) { | ||
275 | return MemFunSelectArgImpl<2, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); | ||
276 | } | ||
221 | 277 | ||
222 | } // namespace FbTk | 278 | } // namespace FbTk |
223 | 279 | ||
diff --git a/src/FbTk/STLUtil.hh b/src/FbTk/STLUtil.hh index d427a17..e08036a 100644 --- a/src/FbTk/STLUtil.hh +++ b/src/FbTk/STLUtil.hh | |||
@@ -26,6 +26,25 @@ | |||
26 | namespace FbTk { | 26 | namespace FbTk { |
27 | namespace STLUtil { | 27 | namespace STLUtil { |
28 | 28 | ||
29 | template<bool C, typename Ta, typename Tb> | ||
30 | struct IfThenElse; | ||
31 | |||
32 | template<typename Ta, typename Tb> | ||
33 | struct IfThenElse<true, Ta, Tb> { | ||
34 | Ta& operator ()(Ta& ta, Tb& tb) const { | ||
35 | return ta; | ||
36 | } | ||
37 | typedef Ta ResultType; | ||
38 | }; | ||
39 | |||
40 | template<typename Ta, typename Tb> | ||
41 | struct IfThenElse<false, Ta, Tb> { | ||
42 | Tb& operator ()(Ta& ta, Tb& tb) const { | ||
43 | return tb; | ||
44 | } | ||
45 | typedef Tb ResultType; | ||
46 | }; | ||
47 | |||
29 | /// calls delete on each item in the container and then clears the container | 48 | /// calls delete on each item in the container and then clears the container |
30 | template <typename A> | 49 | template <typename A> |
31 | void destroyAndClear(A &a) { | 50 | void destroyAndClear(A &a) { |
diff --git a/src/FbTk/SelectArg.hh b/src/FbTk/SelectArg.hh new file mode 100644 index 0000000..83626ad --- /dev/null +++ b/src/FbTk/SelectArg.hh | |||
@@ -0,0 +1,74 @@ | |||
1 | // SelectArg.hh for FbTk | ||
2 | // Copyright (c) 2010 Fluxbox Team (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_STLUTIL_SELECT_ARG_HH | ||
23 | #define FBTK_STLUTIL_SELECT_ARG_HH | ||
24 | |||
25 | #include "STLUtil.hh" | ||
26 | |||
27 | namespace FbTk { | ||
28 | |||
29 | namespace STLUtil { | ||
30 | |||
31 | /** | ||
32 | * Selects a single argument from a maximum set of three arguments at compile time. | ||
33 | * For example: | ||
34 | * \begincode | ||
35 | * SelectArg<0>()( 10, 20, "hello" ); // returns first argument ( 10 ) | ||
36 | * SelectArg<1>()( 10, "hello", 30 ); // returns second argument ( "hello" ) | ||
37 | * SelectArg<2>()( 10, "hello", 30 ); // returns third argument ( 30 ) | ||
38 | * \endcode | ||
39 | * | ||
40 | * The selection of argument 1 and 2 can return the last argument if the | ||
41 | * arguments are less or equal to two. For instance: | ||
42 | * \begincode | ||
43 | * SelectArg<1>()(10); // returns 10 | ||
44 | * SelectArg<2>()(10, 20); // returns 20 | ||
45 | * SelectArg<2>()(10); // returns 10 | ||
46 | * \endcode | ||
47 | */ | ||
48 | template < int N > | ||
49 | struct SelectArg { | ||
50 | |||
51 | template <typename Type1, typename Type2> | ||
52 | typename IfThenElse<N==0, Type1, Type2>::ResultType& operator ()(Type1& a, Type2& b){ | ||
53 | return IfThenElse<N==0, Type1, Type2>()(a, b); | ||
54 | } | ||
55 | |||
56 | template <typename Type1, typename Type2, typename Type3> | ||
57 | typename IfThenElse<N==0, Type1, | ||
58 | typename IfThenElse<N==1, Type2, Type3>::ResultType>::ResultType& | ||
59 | operator () (Type1& a, Type2& b, Type3& c) { | ||
60 | return IfThenElse<N==0, Type1, | ||
61 | typename IfThenElse<N==1, Type2, Type3>::ResultType>() | ||
62 | (a, IfThenElse<N==1, Type2, Type3>() (b, c) ); | ||
63 | } | ||
64 | |||
65 | template < typename Type1 > | ||
66 | Type1 operator() (Type1 a) { | ||
67 | return a; | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | } // end namespace STLUtil | ||
72 | } // end namespace FbTk | ||
73 | |||
74 | #endif // FBTK_STLUTIL_SELECT_ARG_HH | ||
diff --git a/src/tests/testSignals.cc b/src/tests/testSignals.cc index f382289..75f046e 100644 --- a/src/tests/testSignals.cc +++ b/src/tests/testSignals.cc | |||
@@ -49,7 +49,7 @@ struct FunctionClass { | |||
49 | } | 49 | } |
50 | 50 | ||
51 | void takeIt( string& str ) { | 51 | void takeIt( string& str ) { |
52 | cout << "takeIt( " << str << ")" << endl; | 52 | cout << "FunctionClass::takeIt( " << str << " )" << endl; |
53 | } | 53 | } |
54 | 54 | ||
55 | void showMessage( int value, const string& message ) { | 55 | void showMessage( int value, const string& message ) { |
@@ -61,8 +61,21 @@ struct FunctionClass { | |||
61 | void threeArgs( int value, const string& str, double pi ) { | 61 | void threeArgs( int value, const string& str, double pi ) { |
62 | cout << "(" << value << "): " << str << ", pi = " << pi << endl; | 62 | cout << "(" << value << "): " << str << ", pi = " << pi << endl; |
63 | } | 63 | } |
64 | |||
64 | }; | 65 | }; |
65 | 66 | ||
67 | struct Printer { | ||
68 | void printInt(int value) { | ||
69 | cout << "Int:" << value << endl; | ||
70 | } | ||
71 | void printString(string value) { | ||
72 | cout << "string:" << value << endl; | ||
73 | } | ||
74 | void printFloat(float value) { | ||
75 | cout << "Float:" << value << endl; | ||
76 | } | ||
77 | }; | ||
78 | |||
66 | int main() { | 79 | int main() { |
67 | using FbTk::Signal; | 80 | using FbTk::Signal; |
68 | using FbTk::SignalTracker; | 81 | using FbTk::SignalTracker; |
@@ -161,4 +174,22 @@ int main() { | |||
161 | // subject notify its observers | 174 | // subject notify its observers |
162 | source.emit("hello world"); | 175 | source.emit("hello world"); |
163 | } | 176 | } |
177 | |||
178 | // Test argument selector | ||
179 | { | ||
180 | using namespace FbTk; | ||
181 | Signal<void, int, string, float> source; | ||
182 | |||
183 | Printer printer; | ||
184 | source.connect(MemFunSelectArg0(printer, &Printer::printInt)); | ||
185 | source.connect(MemFunSelectArg1(printer, &Printer::printString)); | ||
186 | source.connect(MemFunSelectArg2(printer, &Printer::printFloat)); | ||
187 | |||
188 | source.emit(10, "hello", 3.141592); | ||
189 | |||
190 | Signal<void, string, int> source2; | ||
191 | source2.connect(MemFunSelectArg0(printer, &Printer::printString)); | ||
192 | source2.connect(MemFunSelectArg1(printer, &Printer::printInt)); | ||
193 | source2.emit("world", 37); | ||
194 | } | ||
164 | } | 195 | } |