After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 644207 - Unable to "get" variants of type "a{sv}"
Unable to "get" variants of type "a{sv}"
Status: RESOLVED FIXED
Product: glibmm
Classification: Bindings
Component: general
2.27.x
Other All
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks: 644886
 
 
Reported: 2011-03-08 15:00 UTC by Yannick.Guesnet
Modified: 2011-03-29 09:25 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
A get() method for Variant<VariantBase> (1.74 KB, patch)
2011-03-16 08:31 UTC, Yannick.Guesnet
none Details | Review
Updated patch (3.94 KB, patch)
2011-03-16 09:59 UTC, Yannick.Guesnet
none Details | Review

Description Yannick.Guesnet 2011-03-08 15:00:31 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
Comment 1 Murray Cumming 2011-03-09 12:35:44 UTC
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.
Comment 2 Yannick.Guesnet 2011-03-09 14:41:17 UTC
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...
Comment 3 Yannick.Guesnet 2011-03-16 08:31:09 UTC
Created attachment 183494 [details] [review]
A get() method for Variant<VariantBase>
Comment 4 Yannick.Guesnet 2011-03-16 08:34:30 UTC
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.
Comment 5 Murray Cumming 2011-03-16 09:05:55 UTC
Why doesn't this use g_variant_get_variant() instead of g_variant_get_child_value()?
Comment 6 Yannick.Guesnet 2011-03-16 09:14:13 UTC
Hum, peharps because I have (stupidely ?) copy and adapt the get method of the containers ?
Comment 7 Yannick.Guesnet 2011-03-16 09:31:18 UTC
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).
Comment 8 Murray Cumming 2011-03-16 09:53:41 UTC
(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.
Comment 9 Yannick.Guesnet 2011-03-16 09:59:58 UTC
Created attachment 183505 [details] [review]
Updated patch
Comment 10 Yannick.Guesnet 2011-03-16 10:00:59 UTC
Comment on attachment 183505 [details] [review]
Updated patch

Here is the patch updated with g_variant_get_variant.
I have also add some tests.
Comment 11 Murray Cumming 2011-03-16 10:49:52 UTC
Pushed. Thanks. I also made an extra commit to use _WRAP_METHOD() for this.
Comment 12 Murray Cumming 2011-03-29 09:25:06 UTC
(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