2 * Copyright 2002, The libsigc++ Development Team
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #ifndef _SIGC_VISIT_EACH_HPP_
19 #define _SIGC_VISIT_EACH_HPP_
21 #include <sigc++/type_traits.h>
22 #include <type_traits>
26 #ifndef DOXYGEN_SHOULD_SKIP_THIS
29 //This should really be an inner class of limit_derived_target, without the T_limit template type,
30 //But the SUN CC 5.7 (not earlier versions) compiler finds it ambiguous when we specify a particular specialization of it.
31 //and does not seem to allow us to tell it explicitly that it's an inner class.
32 template <bool I_derived, class T_type, class T_limit>
35 //Specialization for I_derived = false
36 template <class T_type, class T_limit> struct
37 with_type<false, T_type, T_limit>
39 static void execute_(const T_type&, const T_limit&) {}
42 //Specialization for I_derived = true
43 template <class T_type, class T_limit>
44 struct with_type<true, T_type, T_limit>
46 static void execute_(const T_type& _A_type, const T_limit& _A_action)
47 { _A_action.action_(_A_type); }
51 /// Helper struct for visit_each_type().
52 template <class T_target, class T_action>
53 struct limit_derived_target
55 typedef limit_derived_target<T_target, T_action> T_self;
57 template <class T_type>
58 void operator()(const T_type& _A_type) const
60 with_type<std::is_base_of<T_target, T_type>::value || std::is_same<T_target, T_type>::value, T_type, T_self>::execute_(_A_type, *this);
63 limit_derived_target(const T_action& _A_action)
70 // Specialization for T_target pointer types, to provide a slightly different execute_() implementation.
72 template <bool I_derived, class T_type, class T_limit>
73 struct with_type_pointer;
75 //Specialization for I_derived = false
76 template <class T_type, class T_limit>
77 struct with_type_pointer<false, T_type, T_limit>
79 static void execute_(const T_type&, const T_limit&) {}
82 //Specialization for I_derived = true
83 template <class T_type, class T_limit>
84 struct with_type_pointer<true, T_type, T_limit>
86 static void execute_(const T_type& _A_type, const T_limit& _A_action)
87 { _A_action.action_(&_A_type); }
90 template <class T_target, class T_action>
91 struct limit_derived_target<T_target*, T_action>
93 typedef limit_derived_target<T_target*, T_action> T_self;
95 template <class T_type>
96 void operator()(const T_type& _A_type) const
98 with_type_pointer<std::is_base_of<T_target, T_type>::value || std::is_same<T_target, T_type>::value, T_type, T_self>::execute_(_A_type, *this);
101 limit_derived_target(const T_action& _A_action)
108 } /* namespace internal */
109 #endif // DOXYGEN_SHOULD_SKIP_THIS
111 // struct visitor was introduced as a result of https://bugzilla.gnome.org/show_bug.cgi?id=724496
112 // The advantage of using specializations of a template struct instead of overloads of
113 // a template function is described by Herb Sutter in http://www.gotw.ca/publications/mill17.htm
114 // In libsigc++ the main reason for using this technique is that we can avoid using ADL
115 // (argument-dependent lookup), and therefore there is no risk that a visit_each() overload
116 // in e.g. Boost is selected by mistake.
118 /** sigc::visitor<T_functor>::do_visit_each() performs a functor on each of the targets of a functor.
119 * All unknown types just call @a _A_action on them.
120 * Add specializations that specialize the @a T_functor argument for your own
121 * functor types, so that subobjects get visited. This is needed to enable
122 * auto-disconnection support for your functor types.
128 * struct some_functor
130 * void operator()() {}
131 * some_possibly_sigc_trackable_derived_type some_data_member;
132 * some_other_functor_type some_other_functor;
139 * struct visitor<some_ns::some_functor>
141 * template <class T_action>
142 * static void do_visit_each(const T_action& _A_action,
143 * const some_ns::some_functor& _A_target)
145 * sigc::visit_each(_A_action, _A_target.some_data_member);
146 * sigc::visit_each(_A_action, _A_target.some_other_functor);
152 * @ingroup sigcfunctors
154 template <class T_functor>
157 template <class T_action>
158 static void do_visit_each(const T_action& _A_action, const T_functor& _A_functor)
160 _A_action(_A_functor);
164 /** This function performs a functor on each of the targets of a functor.
166 * @ingroup sigcfunctors
168 template <class T_action, class T_functor>
169 void visit_each(const T_action& _A_action, const T_functor& _A_functor)
170 { sigc::visitor<T_functor>::do_visit_each(_A_action, _A_functor); }
172 /** This function performs a functor on each of the targets
173 * of a functor limited to a restricted type.
175 * @ingroup sigcfunctors
177 template <class T_type, class T_action, class T_functor>
178 void visit_each_type(const T_action& _A_action, const T_functor& _A_functor)
180 typedef internal::limit_derived_target<T_type, T_action> type_limited_action;
182 type_limited_action limited_action(_A_action);
184 //specifying the types of the template specialization prevents disconnection of bound trackable references (such as with std::ref()),
185 //probably because the visit_each<> specializations take various different template types,
186 //in various sequences, and we are probably specifying only a subset of them with this.
188 //But this is required by the AIX (and maybe IRIX MipsPro and Tru64) compilers.
189 //I guess that std::ref() therefore does not work on those platforms. murrayc
190 // sigc::visit_each<type_limited_action, T_functor>(limited_action, _A_functor);
192 //g++ (even slightly old ones) is our primary platform, so we could use the non-crashing version.
193 //However, the explicit version also fixes a crash in a slightly more common case: http://bugzilla.gnome.org/show_bug.cgi?id=169225
194 //Users (and distributors) of libsigc++ on AIX (and maybe IRIX MipsPro and Tru64) do
195 //need to use the version above instead, to allow compilation.
197 //Added 2014-03-20: The preceding comment probably does not apply any more,
198 //now when the visit_each<>() overloads have been replaced by visitor<> specializations.
199 //It's probably safe to add explicit template parameters on calls to visit_each(),
200 //visit_each_type() and visitor::do_visit_each(), if necessary.
202 sigc::visit_each(limited_action, _A_functor);
205 } /* namespace sigc */