GNOME Bugzilla – Bug 644207
Unable to "get" variants of type "a{sv}"
Last modified: 2011-03-29 09:25:06 UTC
If I have well understood the Variant API, GVariants of type "a{sv}" should be wrap by the type Glib::Variant< std::map<Glib::ustring, Glib::VariantBase> >. But the method get() does not seem to work with such kind of template as shown by the following example which does not compile : Glib::Variant< std::map<Glib::ustring, Glib::VariantBase> > var_map; std::map< Glib::ustring, Glib::VariantBase > get_map = var_map.get(); I have the following error: In file included from /usr/local/include/glibmm-2.4/glibmm.h:132, from src/testVariant.cpp:8: /usr/local/include/glibmm-2.4/glibmm/variant.h: In member function ‘std::pair<_T1, _T2> Glib::Variant<std::pair<_T1, _T2> >::get() const [with K = Glib::ustring, V = Glib::VariantBase]’: /usr/local/include/glibmm-2.4/glibmm/variant.h:1221: instantiated from ‘std::map<K, V, std::less<_Key>, std::allocator<std::pair<const _Key, _Tp> > > Glib::Variant<std::map<K, V, std::less<_Key>, std::allocator<std::pair<const _Key, _Tp> > > >::get() const [with K = Glib::ustring, V = Glib::VariantBase]’ src/testVariant.cpp:56: instantiated from here /usr/local/include/glibmm-2.4/glibmm/variant.h:1038: erreur: no matching function for call to ‘Glib::Variant<Glib::VariantBase>::get()’ /usr/local/include/glibmm-2.4/glibmm/variant.h:468: note: candidats sont: void Glib::VariantContainerBase::get(Glib::VariantBase&, gsize) const
Glib::VariantBase should not be used as a container element. It's only for use as an output parameter, to which you would pass an instance of a specific derived type. Unfortunately I don't know how we would represent that structure in giomm.
Just a remark: Indeed, in the dictionnary Variant< map<ustring, VariantBase> >, the VariantBase part is in reality a Variant<VariantBase> which is of type "v". We do not really use a "VariantBase" but a Variant<VariantBase>. Things seem right in the following example: // A variant of type v Glib::Variant< Glib::ustring > var_s = Glib::Variant< Glib::ustring >::create("test"); Glib::Variant< Glib::VariantBase > var_v = Glib::Variant< Glib::VariantBase >::create(var_s); std::cout << var_v.get_type_string() << std::endl; Glib::Variant< Glib::ustring > var_s2; var_v.get(var_s2); std::cout << var_s2.get() << std::endl; // A variant of type a{sv} Glib::Variant<Glib::ustring> var_string = Glib::Variant<Glib::ustring>::create("test variant"); std::map< Glib::ustring, Glib::VariantBase > map; map["test key"] = var_string; Glib::Variant< std::map<Glib::ustring, Glib::VariantBase> > var_map = Glib::Variant<std::map<Glib::ustring, Glib::VariantBase> >::create(map); std::cout << var_map.get_type_string() << std::endl; But, of course, this is not because this work that it is the right way to do that...
Created attachment 183494 [details] [review] A get() method for Variant<VariantBase>
Comment on attachment 183494 [details] [review] A get() method for Variant<VariantBase> This patch modify the get() method of Variant<VariantBase>. The method is now like the get methods of the variants with one value. This allows the types the above ones.
Why doesn't this use g_variant_get_variant() instead of g_variant_get_child_value()?
Hum, peharps because I have (stupidely ?) copy and adapt the get method of the containers ?
Another remark about the Variant API : The variants which contain a single value have get() methods like "T get() const" whereas variants which are tuple (VariantContainerBase) have get() methods like "void get(Glib::VariantBase& child, gsize index=0) const". Thus, we have get() methods with different return types (void and T which are incompatibles). For me, this is like (even if it is not) overloadding a method with incompatibles return types (which is not really recommended...). What about rename methods like get(..., gsize index=0) with get_child() ? This is even more accurate with variants manipulating maps or vectors where we have two get methods with different semantics: for example, with maps, we have "std::pair< K, V > get(gsize index) const" and "std::map< K, V > get() const" (return a child and return all content).
(In reply to comment #6) > Hum, peharps because I have (stupidely ?) copy and adapt the get method of the > containers ? Could you update the patch? (In reply to comment #7) > Another remark about the Variant API : The variants which contain a single > value have get() methods like "T get() const" whereas variants which are tuple > (VariantContainerBase) have get() methods like "void get(Glib::VariantBase& > child, gsize index=0) const". > Thus, we have get() methods with different return types (void and T which are > incompatibles). For me, this is like (even if it is not) overloadding a method > with incompatibles return types (which is not really recommended...). Well, I was planning to make sure that all get(VariantBase&) methods had VariantBase get() methods, and vice-versa, once I had applied your patch. Both seem useful. > What about rename methods like get(..., gsize index=0) with get_child() ? > This is even more accurate with variants manipulating maps or vectors where we > have two get methods with different semantics: for example, with maps, we have > "std::pair< K, V > get(gsize index) const" and "std::map< K, V > get() const" > (return a child and return all content). Yes, I was also considering this. Let's do that as a next stage.
Created attachment 183505 [details] [review] Updated patch
Comment on attachment 183505 [details] [review] Updated patch Here is the patch updated with g_variant_get_variant. I have also add some tests.
Pushed. Thanks. I also made an extra commit to use _WRAP_METHOD() for this.
(In reply to comment #8) > > What about rename methods like get(..., gsize index=0) with get_child() ? > > This is even more accurate with variants manipulating maps or vectors where we > > have two get methods with different semantics: for example, with maps, we have > > "std::pair< K, V > get(gsize index) const" and "std::map< K, V > get() const" > > (return a child and return all content). > > Yes, I was also considering this. Let's do that as a next stage. Done in this commit: http://git.gnome.org/browse/glibmm/commit/?id=85252750b27d79458f6b91763c34c1829eac491b