diff options
author | Yannick Guesnet <yannick.guesnet@univ-rouen.fr> | 2011-03-14 20:49:52 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2011-03-16 10:30:38 +0100 |
commit | 4af5c32ac1c325a63d89e5a35ca8647c4a4bb908 (patch) | |
tree | 4e1b34e823936b4fff7c26e88cb798727ca0041c | |
parent | 584a67f8194fce32933ef1cef464a251f56095b9 (diff) | |
download | glibmm-4af5c32ac1c325a63d89e5a35ca8647c4a4bb908.tar.gz |
Variant: Add a cast operator.
* gio/src/glib/src/variant.[ccg|hg]: Add a VariantBase::cast_dynamic()
static method.
* tests/glibmm_variant/main.cc: Add some tests.
This is useful because VariantBase can and will be passed by value sometimes
and DBus may have actual Variant types whose underlying type will not be
known at compile time (this note was by Murray).
Bug #644146
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | glib/src/variant.ccg | 19 | ||||
-rw-r--r-- | glib/src/variant.hg | 29 | ||||
-rw-r--r-- | tests/glibmm_variant/main.cc | 49 |
4 files changed, 110 insertions, 1 deletions
@@ -1,3 +1,17 @@ +2011-03-14 Yannick Guesnet <Yannick.Guesnet@univ-rouen.fr> + + Variant: Add a cast operator. + + * gio/src/glib/src/variant.[ccg|hg]: Add a VariantBase::cast_dynamic() + static method. + * tests/glibmm_variant/main.cc: Add some tests. + + This is useful because VariantBase can and will be passed by value sometimes + and DBus may have actual Variant types whose underlying type will not be + known at compile time (this note was by Murray). + + Bug #644146 + 2011-03-16 Murray Cumming <murrayc@murrayc.com> Fix missing doc-install.pl problem with the tarball build. diff --git a/glib/src/variant.ccg b/glib/src/variant.ccg index 6246304c..c8dc2420 100644 --- a/glib/src/variant.ccg +++ b/glib/src/variant.ccg @@ -90,6 +90,25 @@ void VariantContainerBase::get(VariantBase& child, gsize index) const child.init(gvariant); } +// VariantContainerBase has no method variant_type() +template<> +VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v) +throw(std::bad_cast) +{ + if(v.gobj() == NULL) + { + return VariantContainerBase(); + } + if(v.get_type().is_container()) + { + return VariantContainerBase(const_cast<GVariant*>(v.gobj()), true); + } + else + { + throw std::bad_cast(); + } +} + bool VariantContainerBase::get_maybe(Glib::VariantBase& maybe) const { GVariant* const g_value = diff --git a/glib/src/variant.hg b/glib/src/variant.hg index 71612787..d1e7d6cb 100644 --- a/glib/src/variant.hg +++ b/glib/src/variant.hg @@ -25,6 +25,7 @@ _DEFS(glibmm,glib) #include <vector> #include <map> #include <stdexcept> +#include <typeinfo> namespace Glib { @@ -125,8 +126,31 @@ public: */ void byteswap(VariantBase& result) const; _IGNORE(g_variant_byteswap) + + template<class V_CastTo> + static V_CastTo cast_dynamic(const VariantBase& v) + throw(std::bad_cast); + }; +template<class V_CastTo> +V_CastTo VariantBase::cast_dynamic(const VariantBase& v) +throw(std::bad_cast) +{ + if(v.gobj() == NULL) + { + return V_CastTo(); + } + if(v.is_of_type(V_CastTo::variant_type())) + { + return V_CastTo(const_cast<GVariant*>(v.gobj()), true); + } + else + { + throw std::bad_cast(); + } +} + /** Base class from which string variant classes derive. * @newin{2,28} * @ingroup Variant @@ -256,6 +280,10 @@ public: _IGNORE(g_variant_get_maybe) }; +template<> +VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v) +throw(std::bad_cast); + /** Template class used for the specialization of the Glib::Variant<> classes. * @newin{2,28} * @ingroup Variant @@ -267,7 +295,6 @@ public: typedef T CppType; }; - // Each specialization has (or should have) a variant_type() method that gets // the type. So the C g_variant_get_type() function can be ignored. _IGNORE(g_variant_get_type) diff --git a/tests/glibmm_variant/main.cc b/tests/glibmm_variant/main.cc index cfe12acb..1f463e43 100644 --- a/tests/glibmm_variant/main.cc +++ b/tests/glibmm_variant/main.cc @@ -8,6 +8,8 @@ std::stringstream debug; std::ostream& ostr = debug; +static void test_dynamic_cast(); + int main(int, char**) { Glib::init(); @@ -107,5 +109,52 @@ int main(int, char**) " in the variant are: " << value << '.' << std::endl; } + test_dynamic_cast(); + return EXIT_SUCCESS; } + +static void test_dynamic_cast() +{ + Glib::Variant< int > v1 = Glib::Variant< int >::create(10); + Glib::VariantBase& v2 = v1; + Glib::Variant< int > v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v2); + g_assert(v3.get() == 10); + + Glib::VariantBase v5 = v1; + v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v5); + g_assert(v3.get() == 10); + + Glib::Variant< double > v4; + // v4 contain a NULL GVariant: The cast succeed + v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v4); + + v4 = Glib::Variant< double >::create(1.0); + try + { + v3 = Glib::VariantBase::cast_dynamic<Glib::Variant<int> >(v4); + g_assert_not_reached(); + } + catch(const std::bad_cast& e) + { + } + + // A t-uple + std::vector<Glib::VariantBase> vec_var(2); + vec_var[0] = Glib::Variant<int>::create(1); + vec_var[1] = Glib::Variant<Glib::ustring>::create("coucou"); + Glib::VariantContainerBase var_tuple = Glib::VariantContainerBase::create_tuple(vec_var); + g_assert(var_tuple.get_type_string() == "(is)"); + + v5 = var_tuple; + Glib::VariantContainerBase v6 = Glib::VariantBase::cast_dynamic<Glib::VariantContainerBase >(v5); + + try + { + v6 = Glib::VariantBase::cast_dynamic<Glib::VariantContainerBase >(v1); + g_assert_not_reached(); + } + catch (const std::bad_cast& e) + { + } +} |