all repos — fluxbox @ ceff86b79401c27ed83cad65f59a6621c9a58084

custom fork of the fluxbox windowmanager

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) {
...
}
Henrik Kinnunen fluxgen@fluxbox.org
commit

ceff86b79401c27ed83cad65f59a6621c9a58084

parent

68e90ab84fc8720264694de47c1ac33c401b49e5

4 files changed, 181 insertions(+), 1 deletions(-)

jump to
M src/FbTk/MemFun.hhsrc/FbTk/MemFun.hh

@@ -22,6 +22,8 @@

#ifndef FBTK_MEM_FUN_HH #define FBTK_MEM_FUN_HH +#include "SelectArg.hh" + namespace FbTk { /// No argument functor

@@ -218,6 +220,60 @@ MemFunIgnoreArgs( Object& obj, ReturnType (Object:: *action)(Arg1,Arg2) ) {

return MemFun2IgnoreArgs<ReturnType, Object, Arg1, Arg2>(obj, action); } +/** + * Creates a functor that selects a specific argument of three possible ones + * and uses it for the single argument operator. + */ +template < int ArgNum, typename Functor> +class MemFunSelectArgImpl { +public: + + MemFunSelectArgImpl(Functor func): + m_func(func) { + } + + template <typename Type1, typename Type2, typename Type3> + void operator ()(Type1 a, Type2 b, Type3 c) { + m_func(STLUtil::SelectArg<ArgNum>()(a, b, c)); + } + + template <typename Type1, typename Type2> + void operator ()(Type1 a, Type2 b) { + m_func(STLUtil::SelectArg<ArgNum>()(a, b)); + } + + template <typename Type1> + void operator ()(Type1 a) { + m_func(a); + } + +private: + Functor m_func; +}; + +/// Creates a functor that selects the first argument of three possible ones +/// and uses it for the single argument operator. +template <typename ReturnType, typename Object, typename Arg1> +MemFunSelectArgImpl<0, MemFun1<ReturnType, Object, Arg1> > +MemFunSelectArg0(Object& obj, ReturnType (Object:: *action)(Arg1)) { + return MemFunSelectArgImpl<0, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); +} + +/// Creates a functor that selects the second argument (or first if there is +/// only one) of three possible onesand uses it for the single argument operator. +template <typename ReturnType, typename Object, typename Arg1> +MemFunSelectArgImpl<1, MemFun1<ReturnType, Object, Arg1> > +MemFunSelectArg1(Object& obj, ReturnType (Object:: *action)(Arg1)) { + return MemFunSelectArgImpl<1, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); +} + +/// Creates a functor that selects the third argument (or the last argument if there is +/// less than three arguments) of three possible onesand uses it for the single argument operator. +template <typename ReturnType, typename Object, typename Arg1> +MemFunSelectArgImpl<2, MemFun1<ReturnType, Object, Arg1> > +MemFunSelectArg2(Object& obj, ReturnType (Object:: *action)(Arg1)) { + return MemFunSelectArgImpl<2, MemFun1<ReturnType, Object, Arg1> >(MemFun(obj, action)); +} } // namespace FbTk
M src/FbTk/STLUtil.hhsrc/FbTk/STLUtil.hh

@@ -26,6 +26,25 @@ /// contains useful utilities for STL

namespace FbTk { namespace STLUtil { +template<bool C, typename Ta, typename Tb> +struct IfThenElse; + +template<typename Ta, typename Tb> +struct IfThenElse<true, Ta, Tb> { + Ta& operator ()(Ta& ta, Tb& tb) const { + return ta; + } + typedef Ta ResultType; +}; + +template<typename Ta, typename Tb> +struct IfThenElse<false, Ta, Tb> { + Tb& operator ()(Ta& ta, Tb& tb) const { + return tb; + } + typedef Tb ResultType; +}; + /// calls delete on each item in the container and then clears the container template <typename A> void destroyAndClear(A &a) {
A src/FbTk/SelectArg.hh

@@ -0,0 +1,74 @@

+// SelectArg.hh for FbTk +// Copyright (c) 2010 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef FBTK_STLUTIL_SELECT_ARG_HH +#define FBTK_STLUTIL_SELECT_ARG_HH + +#include "STLUtil.hh" + +namespace FbTk { + +namespace STLUtil { + +/** + * Selects a single argument from a maximum set of three arguments at compile time. + * For example: + * \begincode + * SelectArg<0>()( 10, 20, "hello" ); // returns first argument ( 10 ) + * SelectArg<1>()( 10, "hello", 30 ); // returns second argument ( "hello" ) + * SelectArg<2>()( 10, "hello", 30 ); // returns third argument ( 30 ) + * \endcode + * + * The selection of argument 1 and 2 can return the last argument if the + * arguments are less or equal to two. For instance: + * \begincode + * SelectArg<1>()(10); // returns 10 + * SelectArg<2>()(10, 20); // returns 20 + * SelectArg<2>()(10); // returns 10 + * \endcode + */ +template < int N > +struct SelectArg { + + template <typename Type1, typename Type2> + typename IfThenElse<N==0, Type1, Type2>::ResultType& operator ()(Type1& a, Type2& b){ + return IfThenElse<N==0, Type1, Type2>()(a, b); + } + + template <typename Type1, typename Type2, typename Type3> + typename IfThenElse<N==0, Type1, + typename IfThenElse<N==1, Type2, Type3>::ResultType>::ResultType& + operator () (Type1& a, Type2& b, Type3& c) { + return IfThenElse<N==0, Type1, + typename IfThenElse<N==1, Type2, Type3>::ResultType>() + (a, IfThenElse<N==1, Type2, Type3>() (b, c) ); + } + + template < typename Type1 > + Type1 operator() (Type1 a) { + return a; + } +}; + +} // end namespace STLUtil +} // end namespace FbTk + +#endif // FBTK_STLUTIL_SELECT_ARG_HH
M src/tests/testSignals.ccsrc/tests/testSignals.cc

@@ -49,7 +49,7 @@ cout << "Printing." << endl;

} void takeIt( string& str ) { - cout << "takeIt( " << str << ")" << endl; + cout << "FunctionClass::takeIt( " << str << " )" << endl; } void showMessage( int value, const string& message ) {

@@ -61,7 +61,20 @@ }

void threeArgs( int value, const string& str, double pi ) { cout << "(" << value << "): " << str << ", pi = " << pi << endl; } + }; + +struct Printer { + void printInt(int value) { + cout << "Int:" << value << endl; + } + void printString(string value) { + cout << "string:" << value << endl; + } + void printFloat(float value) { + cout << "Float:" << value << endl; + } +}; int main() { using FbTk::Signal;

@@ -160,5 +173,23 @@ FbTk::relaySignal(source, destination);

// the new signal should now make the old // subject notify its observers source.emit("hello world"); + } + + // Test argument selector + { + using namespace FbTk; + Signal<void, int, string, float> source; + + Printer printer; + source.connect(MemFunSelectArg0(printer, &Printer::printInt)); + source.connect(MemFunSelectArg1(printer, &Printer::printString)); + source.connect(MemFunSelectArg2(printer, &Printer::printFloat)); + + source.emit(10, "hello", 3.141592); + + Signal<void, string, int> source2; + source2.connect(MemFunSelectArg0(printer, &Printer::printString)); + source2.connect(MemFunSelectArg1(printer, &Printer::printInt)); + source2.emit("world", 37); } }