c++-gtk-utils
|
00001 /* Copyright (C) 2009 Chris Vine 00002 00003 The library comprised in this file or of which this file is part is 00004 distributed by Chris Vine under the GNU Lesser General Public 00005 License as follows: 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public License 00009 as published by the Free Software Foundation; either version 2.1 of 00010 the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, but 00013 WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License, version 2.1, for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License, version 2.1, along with this library (see the file LGPL.TXT 00019 which came with this source code package in the c++-gtk-utils 00020 sub-directory); if not, write to the Free Software Foundation, Inc., 00021 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00022 00023 However, it is not intended that the object code of a program whose 00024 source code instantiates a template from this file or uses macros or 00025 inline functions (of any length) should by reason only of that 00026 instantiation or use be subject to the restrictions of use in the GNU 00027 Lesser General Public License. With that in mind, the words "and 00028 macros, inline functions and instantiations of templates (of any 00029 length)" shall be treated as substituted for the words "and small 00030 macros and small inline functions (ten lines or less in length)" in 00031 the fourth paragraph of section 5 of that licence. This does not 00032 affect any other reason why object code may be subject to the 00033 restrictions in that licence (nor for the avoidance of doubt does it 00034 affect the application of section 2 of that licence to modifications 00035 of the source code in this file). 00036 00037 */ 00038 00039 #ifndef CGU_MEM_FUN_H 00040 #define CGU_MEM_FUN_H 00041 00042 /** 00043 * @file mem_fun.h 00044 * @brief This file contains an adaptor to create a functor from a 00045 * class member function to pass to C++ standard algorithms. 00046 * 00047 * \#include <c++-gtk-utils/mem_fun.h> 00048 * 00049 * Cgu::MemFun::make() is provided in order to provide source 00050 * compatibility with the 1.2 series of the library. In C++11 it is 00051 * superseded by std::function, std::mem_fn() and std::bind. 00052 * 00053 * Cgu::MemFun::make() is an adaptor which allows a non-static class 00054 * member function to be called by standard algorithms such as 00055 * std::for_each() or std::transform(), whereby the member function is 00056 * passed a contained object as an argument on iterating through the 00057 * container. It can also be used to make predicates from member 00058 * functions to pass to other algorithms, or indeed to generate a 00059 * general functor object representing a member function with object 00060 * and one or two arguments. It does the equivalent of std::ptr_fun() 00061 * for ordinary functions. 00062 * 00063 * For example, to iterate over a std::vector<int> container object 00064 * named 'vec', calling a class method 'void MyObj::my_method(int)' on 00065 * each iteration, Cgu::MemFun::make() could be invoked as: 00066 * 00067 * @code 00068 * using namespace Cgu; 00069 * std::for_each(vec.begin(), vec.end(), 00070 * MemFun::make(my_obj, &MyObj::my_method)); 00071 * @endcode 00072 * 00073 * As in the case of std::ptr_fun(), when called via std::for_each(), 00074 * the member function called must be a unary function, although an 00075 * additional argument can be bound with std::bind2nd() or 00076 * std::bind1st() to enable it to be used with binary class functions. 00077 * (Note that in many implementations of std::bind1st/2nd, neither the 00078 * free nor the bound argument can be a reference, whether const or 00079 * non-const. A reference argument can be employed with 00080 * Cgu::MemFun::make() where std::bind1st/2nd is not used.) This 00081 * limitation with respect to reference arguments is not present with 00082 * std::mem_fn() and std::bind. 00083 * 00084 * In C++11, the above example could be reproduced as: 00085 * 00086 * @code 00087 * using namespace std::placeholders; // for _1 00088 * std::for_each(vec.begin(), vec.end(), 00089 * std::bind(std::mem_fn(&MyObj::my_method), &my_obj, _1)); 00090 * @endcode 00091 */ 00092 00093 /** 00094 * @namespace Cgu::MemFun 00095 * @brief This namespace contains an adaptor to create a functor from a 00096 * class member function to pass to C++ standard algorithms. 00097 * 00098 * \#include <c++-gtk-utils/mem_fun.h> 00099 * 00100 * Cgu::MemFun::make() is provided in order to provide source 00101 * compatibility with the 1.2 series of the library. In C++11 it is 00102 * superseded by std::function, std::mem_fn() and std::bind. 00103 * 00104 * Cgu::MemFun::make() is an adaptor which allows a non-static class 00105 * member function to be called by standard algorithms such as 00106 * std::for_each() or std::transform(), whereby the member function is 00107 * passed a contained object as an argument on iterating through the 00108 * container. It can also be used to make predicates from member 00109 * functions to pass to other algorithms, or indeed to generate a 00110 * general functor object representing a member function with object 00111 * and one or two arguments. It does the equivalent of std::ptr_fun() 00112 * for ordinary functions. 00113 * 00114 * For example, to iterate over a std::vector<int> container object 00115 * named 'vec', calling a class method 'void MyObj::my_method(int)' on 00116 * each iteration, Cgu::MemFun::make() could be invoked as: 00117 * 00118 * @code 00119 * using namespace Cgu; 00120 * std::for_each(vec.begin(), vec.end(), 00121 * MemFun::make(my_obj, &MyObj::my_method)); 00122 * @endcode 00123 * 00124 * As in the case of std::ptr_fun(), when called via std::for_each(), 00125 * the member function called must be a unary function, although an 00126 * additional argument can be bound with std::bind2nd() or 00127 * std::bind1st() to enable it to be used with binary class functions. 00128 * (Note that in many implementations of std::bind1st/2nd, neither the 00129 * free nor the bound argument can be a reference, whether const or 00130 * non-const. A reference argument can be employed with 00131 * Cgu::MemFun::make() where std::bind1st/2nd is not used.) This 00132 * limitation with respect to reference arguments is not present with 00133 * std::mem_fn() and std::bind. 00134 * 00135 * In C++11, the above example could be reproduced as: 00136 * 00137 * @code 00138 * using namespace std::placeholders; // for _1 00139 * std::for_each(vec.begin(), vec.end(), 00140 * std::bind(std::mem_fn(&MyObj::my_method), &my_obj, _1)); 00141 * @endcode 00142 */ 00143 00144 #include <functional> 00145 #include <c++-gtk-utils/cgu_config.h> 00146 00147 namespace Cgu { 00148 00149 namespace MemFun { 00150 00151 template <class Ret, class Arg, class T> 00152 class Functor1: public std::unary_function<Arg, Ret> { 00153 T* obj; 00154 Ret (T::*func)(Arg); 00155 public: 00156 Ret operator()(Arg arg) const {return (obj->*func)(arg);} 00157 Functor1(T& obj_, Ret (T::*func_)(Arg)): obj(&obj_), func(func_) {} 00158 }; 00159 00160 template <class Ret, class Arg, class T> 00161 Functor1<Ret, Arg, T> make(T& t, 00162 Ret (T::*func)(Arg)) { 00163 return Functor1<Ret, Arg, T>(t, func); 00164 } 00165 00166 /* const version, for binding to const methods */ 00167 00168 template <class Ret, class Arg, class T> 00169 class Functor1_const: public std::unary_function<Arg, Ret> { 00170 const T* obj; 00171 Ret (T::*func)(Arg) const; 00172 public: 00173 Ret operator()(Arg arg) const {return (obj->*func)(arg);} 00174 Functor1_const(const T& obj_, Ret (T::*func_)(Arg) const): obj(&obj_), func(func_) {} 00175 }; 00176 00177 template <class Ret, class Arg, class T> 00178 Functor1_const<Ret, Arg, T> make(const T& t, 00179 Ret (T::*func)(Arg) const) { 00180 return Functor1_const<Ret, Arg, T>(t, func); 00181 } 00182 00183 /* two argument version for use with std::bind* */ 00184 00185 template <class Ret, class Arg1, class Arg2, class T> 00186 class Functor2: public std::binary_function<Arg1, Arg2, Ret> { 00187 T* obj; 00188 Ret (T::*func)(Arg1, Arg2); 00189 public: 00190 Ret operator()(Arg1 arg1, Arg2 arg2) const {return (obj->*func)(arg1, arg2);} 00191 Functor2(T& obj_, Ret (T::*func_)(Arg1, Arg2)): obj(&obj_), func(func_) {} 00192 }; 00193 00194 template <class Ret, class Arg1, class Arg2, class T> 00195 Functor2<Ret, Arg1, Arg2, T> make(T& t, 00196 Ret (T::*func)(Arg1, Arg2)) { 00197 return Functor2<Ret, Arg1, Arg2, T>(t, func); 00198 } 00199 00200 /* const version, for binding to const methods */ 00201 00202 template <class Ret, class Arg1, class Arg2, class T> 00203 class Functor2_const: public std::binary_function<Arg1, Arg2, Ret> { 00204 const T* obj; 00205 Ret (T::*func)(Arg1, Arg2) const; 00206 public: 00207 Ret operator()(Arg1 arg1, Arg2 arg2) const {return (obj->*func)(arg1, arg2);} 00208 Functor2_const(const T& obj_, Ret (T::*func_)(Arg1, Arg2) const): obj(&obj_), func(func_) {} 00209 }; 00210 00211 template <class Ret, class Arg1, class Arg2, class T> 00212 Functor2_const<Ret, Arg1, Arg2, T> make(const T& t, 00213 Ret (T::*func)(Arg1, Arg2) const) { 00214 return Functor2_const<Ret, Arg1, Arg2, T>(t, func); 00215 } 00216 00217 } // namespace MemFun 00218 00219 } // namespace Cgu 00220 00221 #endif