[sigc] API break, affecting those who have made their own visit_each() overload



API break, affecting you if you have added your own overloaded visit_each() function.

An excerpt from the commit message of https://git.gnome.org/browse/libsigc++2/commit/?id=81c778422768f14eb9ed18645a0a4352dd37c2cb
Note: This patch breaks API for some users, but it does not break ABI.
Only users who have added their own visit_each() overloads are affected by
the API break. Their programs will still compile, but there will be run-time
errors, if they rely on auto-disconnection of slots.
Updated instructions for users who implement their own adaptors are found in
the description of sigc::adapts<>.
The API-breaking change will be included in the next release, which will probably be libsigc++  2.3.2.

Most adaptors, derived from sigc::adapts<>, have been accompanied by an overload of sigc::visit_each(). See the description of sigc::adapts at https://developer.gnome.org/libsigc++/2.2/structsigc_1_1adapts.html.

Bug https://bugzilla.gnome.org/show_bug.cgi?id=724496 shows that C++'s overload resolution rules sometimes cause the wrong overload to be selected. The way visit_each() is called has therefore been modified. A visit_each() overload must be replaced by a specialization of struct sigc::visitor<>. The new description of a user-defined adaptor in sigc::adapts<> is

  namespace my_ns
  {
  template <class T_functor>
  struct my_adaptor : public sigc::adapts<T_functor>
  {
    template <class T_arg1=void, class T_arg2=void>
    struct deduce_result_type
    { typedef typename sigc::deduce_result_type<T_functor, T_arg1, T_arg2>::type type; };
    typedef typename sigc::functor_trait<T_functor>::result_type result_type;
    //
    result_type
    operator()() const;
    //
    template <class T_arg1>
    typename deduce_result_type<T_arg1>::type
    operator()(T_arg1 _A_arg1) const;
    //
    template <class T_arg1, class T_arg2>
    typename deduce_result_type<T_arg1, T_arg2>::type
    operator()(T_arg1 _A_arg1, T_arg2 _A_arg2) const;
    //
    // Constructs a my_adaptor object that wraps the passed functor.
    // Initializes adapts<T_functor>::functor_, which is invoked from operator()().
    explicit my_adaptor(const T_functor& _A_functor)
      : sigc::adapts<T_functor>(_A_functor) {}
  };
  } // end namespace my_ns
  //
  // Specialization of sigc::visitor for my_adaptor.
  namespace sigc
  {
  template <class T_functor>
  struct visitor<my_ns::my_adaptor<T_functor> >
  {
    template <class T_action>
    static void do_visit_each(const T_action& _A_action,
                              const my_ns::my_adaptor<T_functor>& _A_target)
    {
      sigc::visit_each(_A_action, _A_target.functor_);
    }
  };
  } // end namespace sigc
 
  If you implement your own adaptor, you must also provide your specialization
  of sigc::visitor<>::do_visit_each<>() that will forward the call to the functor(s)
  your adapter is wrapping. Otherwise, pointers stored within the functor won't be
  invalidated when a sigc::trackable object is destroyed and you can end up
  executing callbacks on destroyed objects.
 
  Your specialization of sigc::visitor<> must be in namespace sigc.

 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]