/* Copyright 2002 - 2016, The libsigc++ Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see .
*/
#ifndef SIGC_VISIT_EACH_HPP
#define SIGC_VISIT_EACH_HPP
#include
#include
#include // std::forward
#include
namespace sigc
{
struct trackable;
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace internal
{
template
constexpr bool is_base_of_or_same_v =
std::is_base_of, std::decay_t>::value ||
std::is_same, std::decay_t>::value;
/// Helper struct for visit_each_trackable().
template
struct limit_trackable_target
{
template
void operator()(T_type&& type) const
{
// Only call action_() if T_Type derives from trackable.
if constexpr (is_base_of_or_same_v)
{
std::invoke(action_, type);
}
else
{
// Prevent 'unreferenced formal parameter' warning from MSVC by 'using' type
static_cast(type);
}
}
explicit limit_trackable_target(const T_action& action) : action_(action) {}
limit_trackable_target(const limit_trackable_target& src) = delete;
limit_trackable_target& operator=(const limit_trackable_target& src) = delete;
limit_trackable_target(limit_trackable_target&& src) = delete;
limit_trackable_target& operator=(limit_trackable_target&& src) = delete;
T_action action_;
};
} /* namespace internal */
#endif // DOXYGEN_SHOULD_SKIP_THIS
// struct visitor was introduced as a result of https://bugzilla.gnome.org/show_bug.cgi?id=724496
// The advantage of using specializations of a template struct instead of overloads of
// a template function is described by Herb Sutter in http://www.gotw.ca/publications/mill17.htm
// In libsigc++ the main reason for using this technique is that we can avoid using ADL
// (argument-dependent lookup), and therefore there is no risk that a visit_each() overload
// in e.g. Boost is selected by mistake.
/** sigc::visitor::do_visit_each() performs a functor on each of the targets of a
* functor.
* All unknown types just call @a action on them.
* Add specializations that specialize the @a T_functor argument for your own
* functor types, so that subobjects get visited. This is needed to enable
* auto-disconnection support for your functor types.
*
* @par Example:
* @code
* namespace some_ns
* {
* struct some_functor
* {
* void operator()() {}
* some_possibly_sigc_trackable_derived_type some_data_member;
* some_other_functor_type some_other_functor;
* };
* }
*
* namespace sigc
* {
* template <>
* struct visitor
* {
* template
* static void do_visit_each(const T_action& action,
* const some_ns::some_functor& target)
* {
* sigc::visit_each(action, target.some_data_member);
* sigc::visit_each(action, target.some_other_functor);
* }
* };
* }
* @endcode
*
* @ingroup sigcfunctors
*/
template
struct visitor
{
template
static void do_visit_each(const T_action& action, const T_functor& functor)
{
action(functor);
}
};
/** This function performs a functor on each of the targets of a functor.
*
* @ingroup sigcfunctors
*/
template
void
visit_each(const T_action& action, const T_functor& functor)
{
sigc::visitor::do_visit_each(action, functor);
}
/** This function performs a functor on each of the targets
* of a functor limited to a restricted type.
*
* It is currently used only to call slot_do_bind and slot_do_unbind
* only on trackable-derived arguments of the functors, like a compile-time version of
* if(dynamic_cast parameters
* in the visitor template specialization.
* TODO: Remove the need for slot_do_bind/slot_do_unbind, limit_trackable_target,
* and visit_each_trackable() by just using a constexpr_if
* (previously known as static_if) if that ends up in C++17.
*
* @ingroup sigcfunctors
*/
template
void
visit_each_trackable(const T_action& action, const T_functor& functor)
{
internal::limit_trackable_target limited_action(action);
sigc::visit_each(limited_action, functor);
}
} /* namespace sigc */
#endif