[glibmm] tests: Add glibmm_interface_move.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm] tests: Add glibmm_interface_move.
- Date: Sat, 22 Aug 2015 19:40:58 +0000 (UTC)
commit 9a81b80ec1952fa01f873af4d7273b7f834d3678
Author: Murray Cumming <murrayc murrayc com>
Date: Sat Aug 22 21:36:20 2015 +0200
tests: Add glibmm_interface_move.
This code got unpleasantly big because I wanted to test a C++
class that wraps a GObject while also implementing a C++ Interface
that wraps a GInterface that the GObject implements. But it seems
to work.
However, the code to test a raw TestInterface is commented out
because the move constructor does not pass the test. I am not sure
if this should even be expected to work:
Interface interface = std::move(object);
or:
Base base = std::move(derived);
Surely that would lose the data (and virtual method table) from the
Derived class anyway?
tests/Makefile.am | 2 +
tests/glibmm_interface_move/main.cc | 292 +++++++++++++++++++++++++++++++++++
2 files changed, 294 insertions(+), 0 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 94d3d8c..e01f418 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -29,6 +29,7 @@ check_PROGRAMS = \
glibmm_date/test \
glibmm_buildfilename/test \
glibmm_interface_implementation/test \
+ glibmm_interface_move/test \
glibmm_mainloop/test \
glibmm_nodetree/test \
glibmm_object_move/test \
@@ -89,6 +90,7 @@ glibmm_date_test_SOURCES = glibmm_date/main.cc
glibmm_interface_implementation_test_SOURCES = glibmm_interface_implementation/main.cc
glibmm_interface_implementation_test_LDADD = $(giomm_ldadd)
+glibmm_interface_move_test_SOURCES = glibmm_interface_move/main.cc
glibmm_mainloop_test_SOURCES = glibmm_mainloop/main.cc
glibmm_nodetree_test_SOURCES = glibmm_nodetree/main.cc
glibmm_object_move_test_SOURCES = glibmm_object_move/main.cc
diff --git a/tests/glibmm_interface_move/main.cc b/tests/glibmm_interface_move/main.cc
new file mode 100644
index 0000000..29662e9
--- /dev/null
+++ b/tests/glibmm_interface_move/main.cc
@@ -0,0 +1,292 @@
+#include <glibmm.h>
+#include <glibmm/private/interface_p.h>
+#include <glibmm/private/object_p.h>
+#include <iostream>
+#include <stdlib.h>
+
+//A basic derived GInterface, just to test Glib::Interface
+
+G_DECLARE_INTERFACE (TestIface, test_Iface, TEST, IFACE, GObject)
+
+struct _TestIface
+{
+ GTypeInterface g_iface;
+};
+
+static void
+test_Iface_init (gpointer)
+{}
+
+GType
+test_Iface_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (TestIface), /* class_size */
+ test_Iface_init, /* base_init */
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "TestIface",
+ &info, GTypeFlags(0));
+ }
+
+ return type;
+}
+
+#define TEST_TYPE_IFACE (test_Iface_get_type ())
+
+
+//A basic derived GObject, just to test Glib::Object.
+typedef struct {
+ GObject parent;
+} TestDerived;
+
+typedef struct {
+ GObjectClass parent;
+} TestDerivedClass;
+
+#define TEST_TYPE_DERIVED (test_derived_get_type ())
+#define TEST_DERIVED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_DERIVED, TestDerived))
+#define TEST_DERIVED_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), TEST_TYPE_DERIVED, TestDerivedClass))
+#define TEST_DERIVED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_DERIVED, TestDerivedClass))
+
+static void test_derived_class_init (TestDerivedClass *)
+{}
+static void test_derived_init (TestDerived *)
+{}
+
+G_DEFINE_TYPE_EXTENDED(TestDerived, test_derived, G_TYPE_OBJECT,
+ 0, G_IMPLEMENT_INTERFACE (TEST_TYPE_IFACE,
+ test_Iface_init))
+
+class TestInterface;
+
+class TestInterface_Class : public Glib::Interface_Class
+{
+public:
+ typedef TestInterface BaseClassType;
+
+ friend class TestInterface;
+
+ const Glib::Interface_Class& init()
+ {
+ if(!gtype_) // create the GType if necessary
+ {
+ // Glib::Interface_Class has to know the interface init function
+ // in order to add interfaces to implementing types.
+ class_init_func_ = &TestInterface_Class::iface_init_function;
+
+ // We can not derive from another interface, and it is not necessary anyway.
+ gtype_ = test_Iface_get_type();
+ }
+
+ return *this;
+ }
+
+ static void iface_init_function(void* /* g_iface */, void* /* iface_data */)
+ {
+ }
+
+ //static Glib::ObjectBase* wrap_new(GObject*);
+};
+
+class TestInterface : public Glib::Interface
+{
+protected:
+ typedef TestInterface_Class CppClassType;
+
+ TestInterface()
+ : Glib::Interface(derived_interface_class_.init())
+ {}
+
+public:
+ //A real application would never make the constructor public.
+ //It would instead have a protectd constructor and a public create() method.
+ TestInterface(GObject* gobject, int i)
+ : Glib::Interface(gobject),
+ i_(i)
+ {
+ }
+
+ static void add_interface(GType gtype_implementer)
+ {
+ derived_interface_class_.init().add_interface(gtype_implementer);
+ }
+
+ TestInterface(const TestInterface& src) = delete;
+ TestInterface& operator=(const TestInterface& src) = delete;
+
+ TestInterface(TestInterface&& src) noexcept
+ : Glib::Interface(std::move(src)),
+ i_(std::move(src.i_))
+ {}
+
+ TestInterface& operator=(TestInterface&& src) noexcept
+ {
+ Glib::Interface::operator=(std::move(src));
+ i_ = std::move(src.i_);
+
+ return *this;
+ }
+
+ int i_;
+
+private:
+ friend class TestInterface_Class;
+ static CppClassType derived_interface_class_;
+};
+
+class DerivedObject_Class : public Glib::Class
+{
+public:
+ typedef GObjectClass BaseClassType;
+ typedef Glib::Object_Class CppClassParent;
+
+ static void class_init_function(void* g_class, void* class_data)
+ {
+ const auto klass = static_cast<BaseClassType*>(g_class);
+ CppClassParent::class_init_function(klass, class_data);
+ }
+
+ const Glib::Class& init()
+ {
+ if(!gtype_) // create the GType if necessary
+ {
+ // Glib::Class has to know the class init function to clone custom types.
+ class_init_func_ = &DerivedObject_Class::class_init_function;
+
+ // This is actually just optimized away, apparently with no harm.
+ // Make sure that the parent type has been created.
+ //CppClassParent::CppObjectType::get_type();
+
+ // Create the wrapper type, with the same class/instance size as the base type.
+ register_derived_type(test_derived_get_type());
+
+ // Add derived versions of interfaces, if the C type implements any interfaces:
+ TestInterface::add_interface(get_type());
+ }
+
+ return *this;
+ }
+};
+
+TestInterface::CppClassType TestInterface::derived_interface_class_; // initialize static member
+
+class DerivedObject
+: public Glib::Object,
+ public TestInterface
+{
+public:
+ typedef DerivedObject_Class CppClassType;
+
+ //A real application would never make the constructor public.
+ //It would instead have a protected constructor and a public create() method.
+ DerivedObject(int i)
+ : Glib::ObjectBase(0),
+ Glib::Object(Glib::ConstructParams(derived_object_class_.init())),
+ i_(i)
+ {
+ }
+
+ DerivedObject(const DerivedObject& src) = delete;
+ DerivedObject& operator=(const DerivedObject& src) = delete;
+
+ DerivedObject(DerivedObject&& src) noexcept
+ : Glib::Object(std::move(src)),
+ TestInterface(std::move(src)),
+ i_(std::move(src.i_))
+ {}
+
+ DerivedObject& operator=(DerivedObject&& src) noexcept
+ {
+ Glib::Object::operator=(std::move(src));
+ TestInterface::operator=(std::move(src));
+ i_ = std::move(src.i_);
+
+ return *this;
+ }
+
+ int i_;
+
+private:
+ friend class DerivedObject_Class;
+ static CppClassType derived_object_class_;
+};
+
+DerivedObject::CppClassType DerivedObject::derived_object_class_; // initialize static member
+
+/* TODO: Shouldn't this work too?
+static
+void test_interface_move_constructor()
+{
+ GObject *gobject = G_OBJECT(g_object_new(TEST_TYPE_DERIVED, nullptr));
+ g_object_ref(gobject);
+
+ TestInterface derived(gobject, 5);
+ std::cout << "debug: gobj(): " << derived.gobj() << std::endl;
+ g_assert(derived.gobj() == gobject);
+ TestInterface derived2(std::move(derived));
+ g_assert_cmpint(derived2.i_, ==, 5);
+ std::cout << "debug: gobj(): " << derived2.gobj() << std::endl;
+ g_assert(derived2.gobj() == gobject);
+}
+
+static
+void test_interface_move_assignment_operator()
+{
+ GObject *gobject = G_OBJECT(g_object_new(TEST_TYPE_DERIVED, nullptr));
+ g_object_ref(gobject);
+
+ TestInterface derived(gobject, 5);
+ //std::cout << "debug: gobj(): " << derived.gobj() << std::endl;
+ g_assert(derived.gobj() == gobject);
+ TestInterface derived2 = std::move(derived);
+ g_assert_cmpint(derived2.i_, ==, 5);
+ //std::cout << "debug: gobj(): " << derived2.gobj() << std::endl;
+ g_assert(derived2.gobj() == gobject);
+}
+*/
+
+
+static
+void test_object_with_interface_move_constructor()
+{
+ DerivedObject derived(5);
+ g_assert_cmpint(derived.i_, ==, 5);
+ GObject *gobject = derived.gobj();
+ g_assert(derived.gobj() == gobject);
+ DerivedObject derived2(std::move(derived));
+ g_assert_cmpint(derived2.i_, ==, 5);
+ g_assert(derived2.gobj() == gobject);
+}
+
+static
+void test_object_with_interface_move_assignment_operator()
+{
+ DerivedObject derived(5);
+ g_assert_cmpint(derived.i_, ==, 5);
+ GObject *gobject = derived.gobj();
+ g_assert(derived.gobj() == gobject);
+ DerivedObject derived2 = std::move(derived);
+ g_assert_cmpint(derived2.i_, ==, 5);
+ g_assert(derived2.gobj() == gobject);
+}
+
+
+int main(int, char**)
+{
+ Glib::init();
+
+ //test_interface_move_constructor();
+ //test_interface_move_assignment_operator();
+
+ test_object_with_interface_move_constructor();
+ test_object_with_interface_move_assignment_operator();
+
+ return EXIT_SUCCESS;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]