summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--glib/glibmm/value.h32
-rw-r--r--glib/glibmm/value_custom.h40
-rw-r--r--tests/glibmm_value/main.cc27
3 files changed, 76 insertions, 23 deletions
diff --git a/glib/glibmm/value.h b/glib/glibmm/value.h
index 9f663810..f2d3f309 100644
--- a/glib/glibmm/value.h
+++ b/glib/glibmm/value.h
@@ -223,18 +223,42 @@ public:
// More spec-compliant compilers (such as Tru64) need this to be near Glib::Object instead.
#ifdef GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
+namespace Traits {
+
+template<typename, typename>
+struct HasGetBaseType;
+
+template<typename T, typename Ret, typename... Args>
+struct HasGetBaseType<T, Ret(Args...)> {
+ template<typename U, U>
+ struct Check;
+
+ template<typename U>
+ static std::true_type
+ Test(Check<Ret(*)(Args...), &U::get_base_type>*);
+
+ template<typename U>
+ static std::false_type Test(...);
+
+ static const bool value = decltype(Test<T>(0))::value;
+ //using type = decltype(Test<T>(0));
+};
+
+} // namespace Traits
+
/** Partial specialization for RefPtr<> to Glib::Object.
* @ingroup glibmmValue
*/
template <class T>
-class Value<Glib::RefPtr<T>> : public ValueBase_Object
+class Value<Glib::RefPtr<T>, typename std::enable_if<Glib::Traits::HasGetBaseType<T, GType()>::value>::type>
+: public ValueBase_Object
{
public:
using CppType = Glib::RefPtr<T>;
static GType value_type() { return T::get_base_type(); }
- void set(const CppType& data) { set_object(data.get()); }
+ void set(const CppType& data) { set_object(const_cast<std::remove_const_t<T>*>(data.get())); }
CppType get() const { return std::dynamic_pointer_cast<T>(get_object_copy()); }
};
@@ -244,8 +268,9 @@ public:
/** Partial specialization for RefPtr<> to const Glib::Object.
* @ingroup glibmmValue
*/
+/*
template <class T>
-class Value<Glib::RefPtr<const T>> : public ValueBase_Object
+class Value<Glib::RefPtr<const T>, typename std::enable_if<std::is_base_of<Glib::ObjectBase, T>::value>::type> : public ValueBase_Object
{
public:
using CppType = Glib::RefPtr<const T>;
@@ -255,6 +280,7 @@ public:
void set(const CppType& data) { set_object(const_cast<T*>(data.get())); }
CppType get() const { return std::dynamic_pointer_cast<T>(get_object_copy()); }
};
+*/
#endif // GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
#endif // GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
diff --git a/glib/glibmm/value_custom.h b/glib/glibmm/value_custom.h
index 9e42dd92..0284888c 100644
--- a/glib/glibmm/value_custom.h
+++ b/glib/glibmm/value_custom.h
@@ -96,7 +96,7 @@ private:
* cannot ensure that no exceptions will be thrown, consider using either
* a normal pointer or a smart pointer to hold your objects indirectly.
*/
-template <class T>
+template <class T, typename Enable = void>
class Value : public ValueBase_Boxed
{
public:
@@ -120,8 +120,8 @@ private:
* No attempt is made to manage the memory associated with the
* pointer, you must take care of that yourself.
*/
-template <class T>
-class Value<T*> : public Value_Pointer<T*>
+template <class T, typename Enable>
+class Value<T*, Enable> : public Value_Pointer<T*>
{
};
@@ -130,8 +130,8 @@ class Value<T*> : public Value_Pointer<T*>
* No attempt is made to manage the memory associated with the
* pointer, you must take care of that yourself.
*/
-template <class T>
-class Value<const T*> : public Value_Pointer<const T*>
+template <class T, typename Enable>
+class Value<const T*, Enable> : public Value_Pointer<const T*>
{
};
@@ -225,29 +225,29 @@ Value_Pointer<PtrT>::get() const
/**** Glib::Value<T> *******************************************************/
// Static data, specific to each template instantiation.
-template <class T>
-GType Value<T>::custom_type_ = 0;
+template <class T, typename Enable>
+GType Value<T, Enable>::custom_type_ = 0;
-template <class T>
+template <class T, typename Enable>
inline void
-Value<T>::set(const typename Value<T>::CppType& data)
+Value<T, Enable>::set(const typename Value<T, Enable>::CppType& data)
{
// Assume the value is already default-initialized. See value_init_func().
*static_cast<T*>(gobject_.data[0].v_pointer) = data;
}
-template <class T>
-inline typename Value<T>::CppType
-Value<T>::get() const
+template <class T, typename Enable>
+inline typename Value<T, Enable>::CppType
+Value<T, Enable>::get() const
{
// Assume the pointer is not NULL. See value_init_func().
return *static_cast<T*>(gobject_.data[0].v_pointer);
}
// static
-template <class T>
+template <class T, typename Enable>
GType
-Value<T>::value_type()
+Value<T, Enable>::value_type()
{
if (!custom_type_)
{
@@ -258,26 +258,26 @@ Value<T>::value_type()
}
// static
-template <class T>
+template <class T, typename Enable>
void
-Value<T>::value_init_func(GValue* value)
+Value<T, Enable>::value_init_func(GValue* value)
{
// Never store a NULL pointer (unless we're out of memory).
value->data[0].v_pointer = new (std::nothrow) T();
}
// static
-template <class T>
+template <class T, typename Enable>
void
-Value<T>::value_free_func(GValue* value)
+Value<T, Enable>::value_free_func(GValue* value)
{
delete static_cast<T*>(value->data[0].v_pointer);
}
// static
-template <class T>
+template <class T, typename Enable>
void
-Value<T>::value_copy_func(const GValue* src_value, GValue* dest_value)
+Value<T, Enable>::value_copy_func(const GValue* src_value, GValue* dest_value)
{
// Assume the source is not NULL. See value_init_func().
const T& source = *static_cast<T*>(src_value->data[0].v_pointer);
diff --git a/tests/glibmm_value/main.cc b/tests/glibmm_value/main.cc
index 47da4645..a824f948 100644
--- a/tests/glibmm_value/main.cc
+++ b/tests/glibmm_value/main.cc
@@ -78,6 +78,10 @@ test()
Glib::init();
+ // TODO: Put this test, of internal stuff, somewhere else.
+ static_assert(Glib::Traits::HasGetBaseType<DerivedObject, GType()>::value,
+ "DerivedObject has no get_base_type().");
+
// RefPtr to Glib::ObjectBase-derived type:
{
GObject* gobject = G_OBJECT(g_object_new(TEST_TYPE_DERIVED, nullptr));
@@ -114,6 +118,29 @@ test()
const auto v = value.get();
assert(v);
}
+
+ {
+ auto foo = std::make_shared<Foo>();
+
+ // custom pointer
+ Glib::Value<std::shared_ptr<Foo>> value;
+ value.init(Glib::Value<std::shared_ptr<Foo>>::value_type()); // TODO: Avoid this step?
+ value.set(foo);
+
+ const auto v = value.get();
+ assert(v);
+ }
+
+ {
+ auto foo = std::make_shared<Foo>();
+
+ Glib::Value<std::shared_ptr<const Foo>> value;
+ value.init(Glib::Value<std::shared_ptr<const Foo>>::value_type()); // TODO: Avoid this step?
+ value.set(foo);
+
+ const auto v = value.get();
+ assert(v);
+ }
}
// Glib::Object RefPtr<>