[glibmm] Add Glib::WeakRef<>



commit bd40d0acec53de33ce6257366613c6e68e40ca57
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Fri Aug 28 16:34:56 2015 +0200

    Add Glib::WeakRef<>
    
    * glib/glibmm/filelist.am: Add weakref.h.
    * glib/glibmm/weakref.h: New file.
    * glib/glibmm.h: Add weakref.h. (Not yet. I'll do it before I push weakref.h.)
    * tests/Makefile.am: Add test case glibmm_weakref.
    * tests/glibmm_weakref/main.cc: New test case. Bug #583399.
    Thanks to worknesday, who attached a first version of WeakRef to
    the bug report. Bug #583399

 glib/glibmm/filelist.am      |    1 +
 glib/glibmm/weakref.h        |  447 ++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am            |    3 +
 tests/glibmm_weakref/main.cc |  174 ++++++++++++++++
 4 files changed, 625 insertions(+), 0 deletions(-)
---
diff --git a/glib/glibmm/filelist.am b/glib/glibmm/filelist.am
index 4de7bad..352a132 100644
--- a/glib/glibmm/filelist.am
+++ b/glib/glibmm/filelist.am
@@ -81,6 +81,7 @@ glibmm_files_extra_h =                        \
        value.h                         \
        value_custom.h                  \
        vectorutils.h                   \
+       weakref.h                       \
        wrap.h                          \
        wrap_init.h
 
diff --git a/glib/glibmm/weakref.h b/glib/glibmm/weakref.h
new file mode 100644
index 0000000..cfdf493
--- /dev/null
+++ b/glib/glibmm/weakref.h
@@ -0,0 +1,447 @@
+#ifndef _GLIBMM_WEAKREF_H
+#define _GLIBMM_WEAKREF_H
+
+/* Copyright (C) 2015 The glibmm 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib-object.h>
+#include <glibmm/refptr.h>
+#include <glibmm/objectbase.h>
+#include <type_traits> // std::is_base_of<>
+#include <utility> // std::swap<>, std::forward<>
+
+namespace Glib
+{
+
+/** WeakRef<> is a weak reference smartpointer.
+ *
+ * WeakRef can store a pointer to any class that is derived from Glib::ObjectBase.
+ *
+ * Unlike a RefPtr, a WeakRef does not contribute to the reference counting of
+ * the underlying object.
+ *
+ * @newin{2,46}
+ */
+template <typename T_CppObject>
+class WeakRef
+{
+  static_assert(std::is_base_of<Glib::ObjectBase,T_CppObject>::value,
+    "Glib::WeakRef can be used only for classes derived from Glib::ObjectBase.");
+
+public:
+  /** Default constructor.
+   *
+   * Create an empty weak reference.
+   */
+  inline WeakRef();
+
+  /// Copy constructor.
+  inline WeakRef(const WeakRef& src);
+
+  /// Move constructor.
+  inline WeakRef(WeakRef&& src);
+
+  /// Copy constructor from different, but castable type.
+  template <typename T_CastFrom>
+  inline WeakRef(const WeakRef<T_CastFrom>& src);
+
+  /// Move constructor from different, but castable type.
+  template <typename T_CastFrom>
+  inline WeakRef(WeakRef<T_CastFrom>&& src);
+
+  /** Constructor from a RefPtr of the same or a castable type.
+   *
+   * Create a weak reference from a RefPtr of the same or a castable type.
+   * If the RefPtr references nothing, an empty weak reference will be constructed.
+   */
+  template <typename T_CastFrom>
+  inline WeakRef(const RefPtr<T_CastFrom>& src);
+
+  /// Destructor.
+  inline ~WeakRef();
+
+  /// Swap the contents of two WeakRef<>.
+  inline void swap(WeakRef& other);
+
+  /// Copy assignment operator.
+  inline WeakRef& operator=(const WeakRef& src);
+
+  /// Move assignment operator.
+  inline WeakRef& operator=(WeakRef&& src);
+
+  /// Copy assignment from different, but castable type.
+  template <typename T_CastFrom>
+  inline WeakRef& operator=(const WeakRef<T_CastFrom>& src);
+
+  /// Move assignment from different, but castable type.
+  template <typename T_CastFrom>
+  inline WeakRef& operator=(WeakRef<T_CastFrom>&& src);
+
+  /// Assignment from a RefPtr of the same or a castable type.
+  template <typename T_CastFrom>
+  inline WeakRef& operator=(const RefPtr<T_CastFrom>& src);
+
+  /** Test whether the WeakRef<> points to any underlying instance.
+   *
+   * Mimics usage of ordinary pointers:
+   * @code
+   * if (ptr)
+   *   do_something();
+   * @endcode
+   *
+   * In a multi-threaded program a <tt>true</tt> return value can become
+   * obsolete at any time, even before the caller has a chance to test it,
+   * because the underlying instance may lose its last reference in another
+   * thread. Use get() if this is not acceptable.
+   */
+  inline explicit operator bool() const;
+
+  /** Create a strong reference to the underlying object.
+   *
+   * This is a thread-safe way to acquire a strong reference to the underlying
+   * object. If the WeakRef is empty, the returned RefPtr will reference nothing.
+   */
+  inline RefPtr<T_CppObject> get() const;
+
+  /// Make this WeakRef empty.
+  inline void reset();
+
+  /** Dynamic cast to derived class.
+   *
+   * The WeakRef can't be cast with the usual notation so instead you can use
+   * @code
+   * ptr_derived = Glib::WeakRef<Derived>::cast_dynamic(ptr_base);
+   * @endcode
+   */
+  template <typename T_CastFrom>
+  static inline WeakRef cast_dynamic(const WeakRef<T_CastFrom>& src);
+
+  /** Static cast to derived class.
+   *
+   * The WeakRef can't be cast with the usual notation so instead you can use
+   * @code
+   * ptr_derived = Glib::WeakRef<Derived>::cast_static(ptr_base);
+   * @endcode
+   */
+  template <typename T_CastFrom>
+  static inline WeakRef cast_static(const WeakRef<T_CastFrom>& src);
+
+  /** Cast to non-const.
+   *
+   * The WeakRef can't be cast with the usual notation so instead you can use
+   * @code
+   * ptr_nonconst = Glib::WeakRef<NonConstType>::cast_const(ptr_const);
+   * @endcode
+   */
+  template <typename T_CastFrom>
+  static inline WeakRef cast_const(const WeakRef<T_CastFrom>& src);
+
+private:
+  // Let all instantiations of WeakRef access private data.
+  template <typename T_CastFrom>
+  friend class WeakRef;
+
+  // If pCppObject != nullptr && gobject == nullptr,
+  // then the caller holds a strong reference.
+  inline void set(T_CppObject* pCppObject, GWeakRef* gobject);
+
+  // WeakRef owns *gobject_, but it does not own *pCppObject_.
+  // Invariant: (!pCppObject_ || gobject_),
+  // i.e. if pCppObject_ != nullptr then also gobject_ != nullptr.
+  T_CppObject* pCppObject_;
+  GWeakRef* gobject_;
+
+  // Some methods would be simpler if gobject_ were a GWeakRef instead of
+  // a GWeakRef*, but then the move constructor and the move assignment
+  // operation would not be efficient.
+
+}; // end class WeakRef
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef()
+:
+pCppObject_(nullptr), gobject_(nullptr)
+{
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef(const WeakRef& src)
+:
+pCppObject_(src.pCppObject_), gobject_(nullptr)
+{
+  if (pCppObject_)
+  {
+    // We must own a strong reference to the underlying GObject while
+    // calling g_weak_ref_init().
+    gpointer ptr = g_weak_ref_get(src.gobject_);
+    if (ptr)
+    {
+      gobject_ = new GWeakRef;
+      g_weak_ref_init(gobject_, pCppObject_->gobj());
+      g_object_unref(ptr);
+    }
+    else
+      pCppObject_ = nullptr;
+  }
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef(WeakRef&& src)
+:
+pCppObject_(src.pCppObject_), gobject_(src.gobject_)
+{
+  src.pCppObject_ = nullptr;
+  src.gobject_ = nullptr;
+}
+
+// The templated ctor allows copy construction from any object that's
+// castable. Thus, it does downcasts:
+//   base_ref = derived_ref
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(const WeakRef<T_CastFrom>& src)
+:
+pCppObject_(src.pCppObject_), gobject_(nullptr)
+{
+  if (pCppObject_)
+  {
+    // We must own a strong reference to the underlying GObject while
+    // calling g_weak_ref_init().
+    gpointer ptr = g_weak_ref_get(src.gobject_);
+    if (ptr)
+    {
+      gobject_ = new GWeakRef;
+      g_weak_ref_init(gobject_, pCppObject_->gobj());
+      g_object_unref(ptr);
+    }
+    else
+      pCppObject_ = nullptr;
+  }
+}
+
+// The templated ctor allows move construction from any object that's
+// castable. Thus, it does downcasts:
+//   base_ref = std::move(derived_ref)
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(WeakRef<T_CastFrom>&& src)
+:
+pCppObject_(src.pCppObject_), gobject_(src.gobject_)
+{
+  src.pCppObject_ = nullptr;
+  src.gobject_ = nullptr;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(const RefPtr<T_CastFrom>& src)
+:
+pCppObject_(src.operator->()), gobject_(nullptr)
+{
+  if (pCppObject_)
+  {
+    gobject_ = new GWeakRef;
+    g_weak_ref_init(gobject_, pCppObject_->gobj());
+  }
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::~WeakRef()
+{
+  if (gobject_)
+  {
+    g_weak_ref_clear(gobject_);
+    delete gobject_;
+  }
+}
+
+template <class T_CppObject>
+void WeakRef<T_CppObject>::swap(WeakRef& other)
+{
+  std::swap(pCppObject_, other.pCppObject_);
+  std::swap(gobject_, other.gobject_);
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const WeakRef& src)
+{
+  set(src.pCppObject_, src.gobject_);
+  return *this;
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(WeakRef&& src)
+{
+  // See RefPtr for an explanation of the swap() technique to implement
+  // copy assignment and move assignment.
+  // This technique is inefficient for copy assignment of WeakRef,
+  // because it involves copy construction + destruction, i.e. in a typical
+  // case g_weak_ref_init() + g_weak_ref_clear(), when a g_weak_ref_set()
+  // would be enough. For move assignment, the swap technique is fine.
+  WeakRef<T_CppObject> temp(std::forward<WeakRef<T_CppObject>>(src));
+  this->swap(temp);
+  return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const WeakRef<T_CastFrom>& src)
+{
+  set(src.pCppObject_, src.gobject_);
+  return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(WeakRef<T_CastFrom>&& src)
+{
+  WeakRef<T_CppObject> temp(std::forward<WeakRef<T_CastFrom>>(src));
+  this->swap(temp);
+  return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
+{
+  T_CppObject* pCppObject = src.operator->();
+  set(pCppObject, nullptr);
+  return *this;
+}
+
+template <class T_CppObject>
+WeakRef<T_CppObject>::operator bool() const
+{
+  if (!pCppObject_)
+    return false;
+
+  gpointer ptr = g_weak_ref_get(gobject_);
+  if (!ptr)
+    return false;
+
+  g_object_unref(ptr);
+  return true;
+}
+
+template <typename T_CppObject>
+RefPtr<T_CppObject> WeakRef<T_CppObject>::get() const
+{
+  RefPtr<T_CppObject> ret;
+
+  if (!pCppObject_)
+    return ret;
+
+  gpointer ptr = g_weak_ref_get(gobject_);
+  if (!ptr)
+    return ret;
+
+  // A RefPtr constructed from pointer expects reference to be done externally.
+  pCppObject_->reference();
+  ret = RefPtr<T_CppObject>(pCppObject_);
+
+  g_object_unref(ptr);
+
+  return ret;
+}
+
+template <typename T_CppObject>
+void WeakRef<T_CppObject>::reset()
+{
+  set(nullptr, nullptr);
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_dynamic(const WeakRef<T_CastFrom>& src)
+{
+  WeakRef<T_CppObject> ret;
+
+  if (!src.pCppObject_)
+    return ret;
+
+  gpointer ptr = g_weak_ref_get(src.gobject_);
+  if (!ptr)
+    return ret;
+
+  // Don't call dynamic_cast<>() unless we know that the referenced object
+  // still exists.
+  T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.pCppObject_);
+  ret.set(pCppObject, nullptr);
+  g_object_unref(ptr);
+
+  return ret;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_static(const WeakRef<T_CastFrom>& src)
+{
+  T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.pCppObject_);
+
+  WeakRef<T_CppObject> ret;
+  ret.set(pCppObject, src.gobject_);
+  return ret;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_const(const WeakRef<T_CastFrom>& src)
+{
+  T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.pCppObject_);
+
+  WeakRef<T_CppObject> ret;
+  ret.set(pCppObject, src.gobject_);
+  return ret;
+}
+
+template <typename T_CppObject>
+void WeakRef<T_CppObject>::set(T_CppObject* pCppObject, GWeakRef* gobject)
+{
+  // We must own a strong reference to the underlying GObject while
+  // calling g_weak_ref_init() or g_weak_ref_set().
+  // If pCppObject != nullptr && gobject == nullptr,
+  // then the caller holds a strong reference.
+
+  // An aim with this moderately complicated method is to keep the same
+  // GWeakRef, calling g_weak_ref_set() when possible, instead of using swap(),
+  // which implies creating a new WeakRef, swapping with *this, and deleting
+  // the new WeakRef.
+
+  gpointer ptr = nullptr;
+  if (pCppObject && gobject)
+    ptr = g_weak_ref_get(gobject);
+
+  pCppObject_ = (ptr || !gobject) ? pCppObject : nullptr;
+  if (pCppObject_ && !gobject_)
+  {
+    gobject_ = new GWeakRef;
+    g_weak_ref_init(gobject_, pCppObject_->gobj());
+  }
+  else if (gobject_)
+    g_weak_ref_set(gobject_, pCppObject_ ? pCppObject_->gobj() : nullptr);
+
+  if (ptr)
+    g_object_unref(ptr);
+}
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+/** Swap the contents of two WeakRef<>.
+ * @relates Glib::WeakRef
+ */
+template <class T_CppObject> inline
+void swap(WeakRef<T_CppObject>& lhs, WeakRef<T_CppObject>& rhs)
+{
+  lhs.swap(rhs);
+}
+
+} // namespace Glib
+
+#endif // _GLIBMM_WEAKREF_H
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e01f418..b2dddc3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ check_PROGRAMS =                              \
        glibmm_null_containerhandle/test        \
        glibmm_refptr/test              \
        glibmm_refptr_sigc_bind/test            \
+       glibmm_weakref/test             \
        glibmm_bytearray/test
 
 TESTS =        $(check_PROGRAMS)
@@ -110,4 +111,6 @@ glibmm_null_containerhandle_test_SOURCES = glibmm_null_containerhandle/main.cc
 glibmm_null_containerhandle_test_LDADD   = $(giomm_ldadd)
 glibmm_refptr_test_SOURCES               = glibmm_refptr/main.cc
 glibmm_refptr_sigc_bind_test_SOURCES     = glibmm_refptr_sigc_bind/main.cc
+glibmm_weakref_test_SOURCES              = glibmm_weakref/main.cc
+glibmm_weakref_test_LDADD                = $(giomm_ldadd)
 glibmm_bytearray_test_SOURCES            = glibmm_bytearray/main.cc
diff --git a/tests/glibmm_weakref/main.cc b/tests/glibmm_weakref/main.cc
new file mode 100644
index 0000000..715ca1d
--- /dev/null
+++ b/tests/glibmm_weakref/main.cc
@@ -0,0 +1,174 @@
+/* Copyright (C) 2015 The glibmm 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm.h>
+#include <giomm.h> //There is no class derived from Glib::Object in glibmm
+#include <iostream>
+#include <cstring>
+#include <utility> // std::move
+#include <glibmm/weakref.h> //!! Until it's included in glibmm.h
+
+int main(int, char**)
+{
+  Glib::init();
+  bool success = true;
+
+  // A Glib::WeakRef cannot be created from a Glib::RefPtr<Glib::Bytes>,
+  // because Glib::Bytes is not derived from Glib::ObjectBase.
+  //const int bdata = 1234;
+  //Glib::RefPtr<Glib::Bytes> bytes = Glib::Bytes::create(&bdata, sizeof bdata);
+  //Glib::WeakRef<Glib::Bytes> weakbytes = bytes; // does not compile
+
+  // Gio::MemoryInputStream
+  Glib::RefPtr<Gio::MemoryInputStream> memstream1 = Gio::MemoryInputStream::create();
+  const char data[] = "Some arbitrary data";
+  memstream1->add_data(data, sizeof data, Gio::MemoryInputStream::SlotDestroyData());
+
+  // Downcast copy, followed by upcast.
+  Glib::WeakRef<Gio::MemoryInputStream> weakmemstream1 = memstream1;
+  Glib::WeakRef<Gio::InputStream> weakstream1 = weakmemstream1;
+  Glib::WeakRef<Gio::MemoryInputStream> weakmemstream2 =
+    Glib::WeakRef<Gio::MemoryInputStream>::cast_dynamic(weakstream1);
+  Glib::RefPtr<Gio::MemoryInputStream> memstream2 = weakmemstream2.get();
+  if (memstream2)
+  {
+    char buffer[200];
+    gsize bytes_read = 0;
+    try
+    {
+      memstream2->read_all(buffer, sizeof buffer, bytes_read);
+      std::cout << buffer << std::endl;
+      success &= std::strcmp(buffer, data) == 0;
+    }
+    catch (const Glib::Error& ex)
+    {
+      std::cout << "Error reading from memory stream: " << ex.what() << std::endl;
+      success = false;
+    }
+  }
+  else
+  {
+    std::cout << "!memstream2" << std::endl;
+    success = false;
+  }
+
+  // Move construction.
+  Glib::WeakRef<Gio::MemoryInputStream> weakmemstream3(std::move(weakmemstream1));
+  if (weakmemstream1.get() || !weakmemstream3.get())
+  {
+    success = false;
+    if (weakmemstream1.get())
+      std::cout << "weakmemstream1 || !weakmemstream3: weakmemstream1" << std::endl;
+    if (!weakmemstream3.get())
+      std::cout << "weakmemstream1 || !weakmemstream3: !weakmemstream3" << std::endl;
+  }
+  else
+  {
+    // Move assignment.
+    weakmemstream2 = std::move(weakmemstream3);
+    if (!weakmemstream2 || weakmemstream3)
+    {
+      success = false;
+      if (!weakmemstream2.get())
+        std::cout << "!weakmemstream2 || weakmemstream3: !weakmemstream2" << std::endl;
+      if (weakmemstream3.get())
+        std::cout << "!weakmemstream2 || weakmemstream3: weakmemstream3" << std::endl;
+    }
+    else
+    {
+      // Downcast move, followed by upcast.
+      weakstream1 = std::move(weakmemstream2);
+      weakmemstream1 = Glib::WeakRef<Gio::MemoryInputStream>::cast_dynamic(weakstream1);
+      if (weakmemstream2 || !weakmemstream1)
+      {
+        success = false;
+        if (weakmemstream2)
+          std::cout << "weakmemstream2 || !weakmemstream1: weakmemstream2" << std::endl;
+        if (!weakmemstream1)
+          std::cout << "weakmemstream2 || !weakmemstream1: !weakmemstream1" << std::endl;
+      }
+    }
+  }
+
+  // Gio::SimpleAction
+  Glib::RefPtr<Gio::SimpleAction> action1 = Gio::SimpleAction::create("Action1");
+
+  Glib::ustring name = action1->get_name();
+  std::cout << "The name is '" << name << "'." << std::endl;
+  success &= name == "Action1";
+
+  Glib::WeakRef<Gio::SimpleAction> weakaction1 = action1;
+  Glib::WeakRef<Gio::SimpleAction> weakaction2 = weakaction1;
+
+  // A second RefPtr
+  Glib::RefPtr<Gio::SimpleAction> action2 = weakaction1.get();
+  if (action2)
+  {
+    name = action2->get_name();
+    std::cout << "The name is '" << name << "'." << std::endl;
+    success &= name == "Action1";
+  }
+  else
+  {
+    std::cout << "!action2" << std::endl;
+    success = false;
+  }
+
+  weakaction1.reset();
+  if (weakaction1.get())
+  {
+    std::cout << "weakaction1" << std::endl;
+    success = false;
+  }
+
+  action2 = weakaction2.get();
+  if (action2)
+  {
+    name = action2->get_name();
+    std::cout << "The name is '" << name << "'." << std::endl;
+    success &= name == "Action1";
+  }
+  else
+  {
+    std::cout << "!action2" << std::endl;
+    success = false;
+  }
+
+  // Reset one of the RefPtrs. One remains.
+  action1.reset();
+  action2 = weakaction2.get();
+  if (action2)
+  {
+    name = action2->get_name();
+    std::cout << "The name is '" << name << "'." << std::endl;
+    success &= name == "Action1";
+  }
+  else
+  {
+    std::cout << "!action2" << std::endl;
+    success = false;
+  }
+
+  // Reset the other RefPtr as well.
+  action2.reset();
+  if (weakaction2.get())
+  {
+    std::cout << "weakaction2" << std::endl;
+    success = false;
+  }
+
+  return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}


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