/* Copyright 2005 - 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_LIMIT_REFERENCE_H
#define SIGC_LIMIT_REFERENCE_H
#include
#include
#include
namespace sigc
{
/** A limit_reference object stores a reference (Foo&), but makes sure that,
* if Foo inherits from sigc::trackable, then visit_each<>() will "limit" itself to the
* sigc::trackable reference instead of the derived reference. This avoids use of
* a reference to the derived type when the derived destructor has run. That can be
* a problem when using virtual inheritance.
*
* If Foo inherits from trackable then both the derived reference and the
* sigc::trackable reference are stored, so we can later retrieve the sigc::trackable
* reference without doing an implicit conversion. To retrieve the derived reference
* (so that you invoke methods or members of it), use invoke(). To retrieve the trackable
* reference (so that you can call visit_each() on it), you use visit().
*
* If Foo does not inherit from sigc::trackable then invoke() and visit() just return the
* derived reference.
*
* This is used for bound (sigc::bind) slot parameters (via bound_argument), bound return values,
* and, with mem_fun(), the reference to the handling object.
*
* - @e T_type The type of the reference.
*/
template>::value>
class limit_reference
{
public:
using reference_type = typename std::remove_volatile_t;
limit_reference() = delete;
/** Constructor.
* @param target The reference to limit.
*/
explicit limit_reference(reference_type& target) : visited(target) {}
limit_reference(const limit_reference& src) = default;
limit_reference& operator=(const limit_reference& src) = default;
limit_reference(limit_reference&& src) = default;
limit_reference& operator=(limit_reference&& src) = default;
/** Retrieve the entity to visit for visit_each().
* Depending on the template specialization, this is either a derived reference, or
* sigc::trackable& if T_type derives from sigc::trackable.
* @return The reference.
*/
inline const reference_type& visit() const { return visited; }
/** Retrieve the reference.
* This is always a reference to the derived instance.
* @return The reference.
*/
inline T_type& invoke() const { return visited; }
private:
/** The reference.
*/
reference_type& visited;
};
/** limit_reference object for a class that derives from trackable.
* - @e T_type The type of the reference.
*/
template
class limit_reference
{
public:
using reference_type = typename std::remove_volatile_t;
/** Constructor.
* @param target The reference to limit.
*/
limit_reference(reference_type& target) : visited(target), invoked(target) {}
/** Retrieve the entity to visit for visit_each().
* Depending on the template specialization, this is either a derived reference, or
* sigc::trackable& if T_type derives from sigc::trackable.
* @return The reference.
*/
inline const trackable& visit() const { return visited; }
/** Retrieve the reference.
* This is always a reference to the derived instance.
* @return The reference.
*/
inline T_type& invoke() const { return invoked; }
private:
using trackable_type =
typename std::conditional_t::value, const trackable, trackable>;
/** The trackable reference.
*/
trackable_type& visited;
/** The reference.
*/
reference_type& invoked;
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/** Implementation of visitor specialized for the $1limit_reference
* class, to call visit_each() on the entity returned by the $1limit_reference's
* visit() method.
* @tparam T_type The type of the reference
* @tparam T_action The type of functor to invoke.
* @param action The functor to invoke.
* @param target The visited instance.
*/
template
struct visitor>
{
template
static void do_visit_each(const T_action& action, const limit_reference& target)
{
sigc::visit_each(action, target.visit());
}
};
#endif // DOXYGEN_SHOULD_SKIP_THIS
} /* namespace sigc */
#endif /* SIGC_LIMIT_REFERENCE_H */