1/* Copyright 2010 The glibmm Development Team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17_DEFS(glibmm,glib)
18
19#include <glibmmconfig.h>
20#include <glibmm/varianttype.h>
21#include <glibmm/variantiter.h>
22#include <glibmm/variantdbusstring.h>
23#include <glibmm/refptr.h>
24#include <glibmm/ustring.h>
25#include <glibmm/error.h>
26#include <utility>
27#include <vector>
28#include <map>
29#include <memory>
30#include <tuple>
31#include <stdexcept>
32#include <typeinfo>
33#include <cstddef>
34
35namespace Glib
36{
37class Bytes;
38
39/** @defgroup Variant Variant Data Types
40 *
41 * The Variant classes deal with strongly typed
42 * variant data. A Variant stores a value along with
43 * information about the type of that value. The range of possible
44 * values is determined by the type. The type system used is VariantType.
45 *
46 * See the VariantBase class and its derived types, such as VariantContainerBase,
47 * and the Variant<> template type.
48 *
49 * Variant instances always have a type and a value (which are given
50 * at construction time). The type and value of a Variant
51 * can never change other than by the Variant itself being
52 * destroyed.  A Variant cannot contain a pointer.
53 *
54 * Variant is heavily optimised for dealing with data in serialised
55 * form. It works particularly well with data located in memory-mapped
56 * files. It can perform nearly all deserialisation operations in a
57 * small constant time, usually touching only a single memory page.
58 * Serialised Variant data can also be sent over the network.
59 *
60 * Variant is largely compatible with D-Bus.  Almost all types of
61 * Variant instances can be sent over D-Bus.  See VariantType for
62 * exceptions.
63 *
64 * There is a Python-inspired text language for describing Variant
65 * values. Variant includes a printer for this language and a parser
66 * with type inferencing.
67 */
68
69//Note: We wrap this because it is thrown by GtkBuilder's functions.
70// See https://bugzilla.gnome.org/show_bug.cgi?id=708206
71// It would also be thrown by parse() if we wrap g_variant_parse().
72// Now (2014-01-30) it's also thrown by Gio::Action::parse_detailed_name().
73/** %Exception class for Variant parse errors.
74 */
75_WRAP_GERROR(VariantParseError, GVariantParseError, G_VARIANT_PARSE_ERROR, NO_GTYPE, decl_prefix GLIBMM_API)
76
77//TODO: Add this documentation from the API if we are confident of it for the C++ wrapper:
78// #GVariant is completely threadsafe.  A #GVariant instance can be
79// concurrently accessed in any way from any number of threads without
80// problems.
81// Note that we don't copy GVariant's documentation about Memory Use because
82// it seems easy to get out of sync and people can look at that C documentation if necessary.
83
84/** This is the base class for all Variant types.
85 *
86 * If the actual type is known at compile-time then you should use a specific
87 * Variant<>, such as Variant<int>. Otherwise, you may use get_type(),
88 * is_of_type(), or cast_dynamic().
89 *
90 * @newin{2,28}
91 * @ingroup Variant
92 */
93class GLIBMM_API VariantBase
94{
95  _CLASS_OPAQUE_COPYABLE(VariantBase, GVariant, NONE, g_variant_ref_sink, g_variant_unref, GLIBMM_API)
96  _CUSTOM_CTOR_CAST()
97  _IGNORE(g_variant_ref, g_variant_ref_sink, g_variant_take_ref, g_variant_unref,
98    g_variant_get, g_variant_get_va)
99public:
100
101_DEPRECATE_IFDEF_START
102  /** This typedef is just to make it more obvious that
103   * our operator const void* should be used like operator bool().
104   *
105   * @deprecated Use the explicit operator bool() instead.
106   */
107  using BoolExpr = const void*;
108
109  /** Test whether the Variant has an underlying instance.
110   *
111   * Mimics usage of pointers:
112   * @code
113   *   if (variant)
114   *     do_something();
115   * @endcode
116   *
117   * @deprecated Use the explicit operator bool() instead.
118   *
119   * @newin{2,36}
120   */
121   operator BoolExpr() const;
122_DEPRECATE_IFDEF_END
123
124   /** Test whether the Variant has an underlying instance.
125    *
126    * @newin{2,50}
127    */
128   explicit operator bool() const;
129
130  /** Replace the underlying GVariant.
131   * This is for use by methods that take a VariantBase& as an output
132   * parameter.
133   *
134   * @param cobject The GVariant* obtained from a C function.
135   * @param take_a_reference Whether this method should take a reference, for
136   * instance if the C function has not given one.
137   */
138  void init(const GVariant* cobject, bool take_a_reference = false);
139
140// It's necessary to take an extra reference of the 'const GVariantType*'
141// returned by g_variant_get_type() because it doesn't do that already.
142#m4 _CONVERSION(`const GVariantType*',`VariantType',`Glib::wrap(const_cast<GVariantType*>($3), true)')
143  _WRAP_METHOD(VariantType get_type() const, g_variant_get_type)
144
145  _WRAP_METHOD(std::string get_type_string() const, g_variant_get_type_string)
146  _WRAP_METHOD(bool is_floating() const, g_variant_is_floating)
147  _WRAP_METHOD(bool is_of_type(const VariantType& type) const, g_variant_is_of_type)
148  _WRAP_METHOD(bool is_container() const, g_variant_is_container)
149  _WRAP_METHOD(GVariantClass classify() const, g_variant_classify)
150
151  _WRAP_METHOD(gsize get_size() const, g_variant_get_size)
152  _WRAP_METHOD(gconstpointer get_data(), g_variant_get_data, deprecated "Use the const version instead.")
153  _WRAP_METHOD(gconstpointer get_data() const, g_variant_get_data, newin "2,46")
154  _WRAP_METHOD(Glib::RefPtr<const Glib::Bytes> get_data_as_bytes() const, g_variant_get_data_as_bytes, newin "2,46")
155  _WRAP_METHOD(void store(gpointer data) const, g_variant_store)
156
157  _WRAP_METHOD(Glib::ustring print(bool type_annotate = false) const, g_variant_print)
158  _IGNORE(g_variant_print_string)
159
160  #m4 _CONVERSION(`const VariantBase&',`gconstpointer',`const_cast<GVariant*>(($3).gobj())')
161  _WRAP_METHOD(guint hash() const, g_variant_hash)
162
163  /** Checks if @a *this and @a other have the same type and value.
164   *
165   * @newin{2,24}
166   *
167   * @param other The Variant to compare with.
168   * @return <tt>true</tt> if @a *this and @a other are equal.
169   */
170  _WRAP_METHOD(bool equal(const VariantBase& other) const, g_variant_equal)
171
172  /** Gets a VariantBase instance that has the same value as this variant and
173   * is trusted to be in normal form.
174   *
175   * If this variant is already trusted to be in normal form then a new
176   * reference to the variant is returned.
177   *
178   * If this variant is not already trusted, then it is scanned to check if it
179   * is in normal form. If it is found to be in normal form then it is marked
180   * as trusted and a new reference to it is returned.
181   *
182   * If this variant is found not to be in normal form then a new trusted
183   * VariantBase is created with the same value as this variant.
184   *
185   * It makes sense to call this function if you've received variant data from
186   * untrusted sources and you want to ensure your serialised output is
187   * definitely in normal form.
188   *
189   * @param result A location in which to store the trusted VariantBase.
190   * @newin{2,24}
191   */
192  void get_normal_form(VariantBase& result) const;
193  _IGNORE(g_variant_get_normal_form)
194
195  _WRAP_METHOD(bool is_normal_form() const, g_variant_is_normal_form)
196
197  /** Performs a byteswapping operation on the contents of this variant. The
198   * result is that all multi-byte numeric data contained in the variant is
199   * byteswapped. That includes 16, 32, and 64bit signed and unsigned integers
200   * as well as file handles and double precision floating point values.
201   *
202   * This function is an identity mapping on any value that does not contain
203   * multi-byte numeric data. That include strings, booleans, bytes and
204   * containers containing only these things (recursively).
205   *
206   * The returned value is always in normal form and is marked as trusted.
207   *
208   * @param result A location in which to store the byteswapped form of this
209   * variant.
210   * @newin{2,24}
211   */
212   void byteswap(VariantBase& result) const;
213   _IGNORE(g_variant_byteswap)
214
215   _WRAP_METHOD(bool check_format_string(const std::string& format_string, bool copy_only = false) const, g_variant_check_format_string)
216
217   //Ignore private API from gvariant-core.h:
218   _IGNORE(g_variant_is_trusted, g_variant_get_type_info)
219
220   /** Cast to a specific variant type.
221    * For instance:
222    * @code
223    * Variant<std::string> derived = VariantBase::cast_dynamic< Variant<std::string> >(base);
224    * @endcode
225    *
226    * @param v The variant to cast to a specific type.
227    * @result The variant as a specific type.
228    * @throws std::bad_cast if the Variant was not of the expected type.
229    */
230   template<class V_CastTo>
231   static V_CastTo cast_dynamic(const VariantBase& v);
232
233   _IGNORE(g_variant_dict_new)
234
235protected:
236#ifndef DOXYGEN_SHOULD_SKIP_THIS
237  /** Used by cast_dynamic().
238   * In addition to an exact match, the following casts are possible:
239   * - VARIANT_TYPE_OBJECT_PATH and VARIANT_TYPE_SIGNATURE can be cast to
240   *   VARIANT_TYPE_STRING (Glib::ustring).
241   * - VARIANT_TYPE_STRING, VARIANT_TYPE_OBJECT_PATH and VARIANT_TYPE_SIGNATURE
242   *   can be cast to VARIANT_TYPE_BYTESTRING (std::string).
243   * - VARIANT_TYPE_HANDLE can be cast to VARIANT_TYPE_INT32.
244   *
245   * These casts are possible also when they are parts of a more complicated type.
246   * E.g. in Variant<std::map<Glib::ustring, std::vector<std::string> > > the map's keys
247   * can be VARIANT_TYPE_OBJECT_PATH and the vector's elements can be VARIANT_TYPE_SIGNATURE.
248   * @newin{2,46}
249   */
250  bool is_castable_to(const VariantType& supertype) const;
251#endif //DOXYGEN_SHOULD_SKIP_THIS
252
253private:
254  /** Relational operators are deleted to prevent invalid conversion
255   * to const void*.
256   */
257  bool operator<(const VariantBase& src) const;
258
259  /// See operator<().
260  bool operator<=(const VariantBase& src) const;
261
262  /// See operator<().
263  bool operator>(const VariantBase& src) const;
264
265  /// See operator<().
266  bool operator>=(const VariantBase& src) const;
267
268  /// See operator<().
269  bool operator==(const VariantBase& src) const;
270
271  /// See operator<().
272  bool operator!=(const VariantBase& src) const;
273};
274
275template<class V_CastTo>
276V_CastTo VariantBase::cast_dynamic(const VariantBase& v)
277{
278  if(!(v.gobj()))
279  {
280    return V_CastTo();
281  }
282  if(v.is_castable_to(V_CastTo::variant_type()))
283  {
284    return V_CastTo(const_cast<GVariant*>(v.gobj()), true);
285  }
286  else
287  {
288   throw std::bad_cast();
289  }
290}
291
292/** Base class from which string variant classes derive.
293 * @newin{2,28}
294 * @ingroup Variant
295 */
296class GLIBMM_API VariantStringBase : public VariantBase
297{
298  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
299  _CLASS_GENERIC(VariantStringBase, GVariant)
300
301public:
302  using CType = GVariant*;
303  using CppType = VariantStringBase;
304
305  /// Default constructor.
306  VariantStringBase();
307
308  /** GVariant constructor.
309   * @param castitem The GVariant to wrap.
310   * @param take_a_reference Whether to take an extra reference of the
311   * GVariant or not (not taking one could destroy the GVariant with the
312   * wrapper).
313   */
314  explicit VariantStringBase(GVariant* castitem,  bool take_a_reference = false);
315
316  /** Creates a D-Bus object path variant with the contents of @a object_path.
317   * @a object_path must be a valid D-Bus object path. Use is_object_path() if unsure.
318   *
319   * @param[out] output A location in which to store the new object path variant
320   * instance.
321   * @param object_path An object path string.
322   * @newin{2,28}
323   */
324  static void create_object_path(VariantStringBase& output,
325    const std::string& object_path);
326  _IGNORE(g_variant_new_object_path)
327
328  _WRAP_METHOD(static bool is_object_path(const std::string& string), g_variant_is_object_path)
329
330  /** Creates a D-Bus type signature variant with the contents of @a signature.
331   * @a signature must be a valid D-Bus type signature. Use is_signature() if unsure.
332   *
333   * @param[out] output A location in which to store the new signature variant
334   * instance.
335   * @param signature A signature string.
336   * @newin{2,28}
337   */
338  static void create_signature(VariantStringBase& output,
339    const std::string& signature);
340  _IGNORE(g_variant_new_signature)
341
342  _WRAP_METHOD(static bool is_signature(const std::string& string), g_variant_is_signature)
343};
344
345/** The base class for multiple-item Variants, such as Variants containing
346 * tuples or arrays, and also for maybe-typed (that is, nullable) Variant types.
347 *
348 * @newin{2,28}
349 * @ingroup Variant
350 */
351class GLIBMM_API VariantContainerBase : public VariantBase
352{
353  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
354  _CLASS_GENERIC(VariantContainerBase, GVariant)
355
356public:
357  using CType = GVariant*;
358  using CppType = VariantContainerBase;
359
360  /// Default constructor.
361  VariantContainerBase();
362
363  /** GVariant constructor.
364   * @param castitem The GVariant to wrap.
365   * @param take_a_reference Whether to take an extra reference of the
366   * GVariant or not (not taking one could destroy the GVariant with the
367   * wrapper).
368   */
369  explicit VariantContainerBase(GVariant* castitem, bool take_a_reference = false);
370
371  /** Create a tuple variant from a vector of its variant children.
372   * @param children The vector containing the children of the container.
373   * @return The newly created tuple variant (as a VariantContainerBase).
374   */
375  static VariantContainerBase create_tuple(const std::vector<VariantBase>& children);
376
377  /** Create a tuple variant with a single variant child.
378   * @param child The child variant.
379   * @return The newly created tuple variant (as a VariantContainerBase).
380   */
381  static VariantContainerBase create_tuple(const VariantBase& child);
382
383  _WRAP_METHOD_DOCS_ONLY(g_variant_new_maybe)
384  static VariantContainerBase create_maybe(const VariantType& child_type,
385    const VariantBase& child = VariantBase());
386
387  _WRAP_METHOD(gsize get_n_children() const, g_variant_n_children)
388
389  /** Reads a child item out of this instance. This method is valid for
390   * variants, maybes, arrays, tuples and dictionary entries.
391   *
392   * It is an error if @a index is greater than the number of child items in
393   * the container. See get_n_children().
394   *
395   * This function is O(1).
396   *
397   * @param index The index of the child to fetch.
398   * @param child A location in which to store the child at the specified
399   * index.
400   * @throw std::out_of_range
401   * @newin{2,28}
402   */
403  void get_child(VariantBase& child, gsize index = 0) const;
404  _IGNORE(g_variant_get_child, g_variant_get_child_value)
405
406#m4 _CONVERSION(`GVariant*',`VariantBase',`Glib::wrap($3)')
407
408  _WRAP_METHOD(VariantBase get_child(gsize index = 0), g_variant_get_child_value)
409
410  /* TODO?:
411  /// A get() method to return the contents of the variant in the container.
412  template <class DataType>
413  DataType get_child(gsize index = 0) const;
414  */
415
416  /** If this is a maybe-typed instance, try to extract its value. If there is
417   * no value (the value is <tt>nothing</tt>), return <tt>false</tt>. Otherwise,
418   * the value is copied to the supplied Variant and <tt>true</tt> is returned.
419   *
420   * @param maybe A place in which to return the value, if it isn’t
421   * <tt>nothing</tt>.
422   * @newin{2,28}
423   */
424  bool get_maybe(VariantBase& maybe) const;
425  _IGNORE(g_variant_get_maybe)
426
427protected:
428#ifndef DOXYGEN_SHOULD_SKIP_THIS
429  /** Used by get_iter() in the subclasses.
430   * @newin{2,46}
431   */
432  VariantIter get_iter(const VariantType& container_variant_type) const;
433#endif //DOXYGEN_SHOULD_SKIP_THIS
434};
435
436template<>
437GLIBMM_API VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v);
438
439/** Template class used for the specialization of the Variant<> classes.
440 * @newin{2,28}
441 * @ingroup Variant
442 */
443template<class T>
444class Variant : public VariantBase
445{
446public:
447  using CppType = T;
448};
449
450/****************** Specializations ***********************************/
451
452/** Specialization of Variant containing a VariantBase.
453 * Perhaps the main use of this is as a maybe-typed (i.e. nullable) Variant, as
454 * it inherits the methods create_maybe() and get_maybe() from
455 * VariantContainerBase, plus get_n_children() to allow checking whether there
456 * is a contained value, i.e. the inner Variant is not <tt>nothing</tt>.
457 *
458 * @newin{2,28}
459 * @ingroup Variant
460 */
461template<>
462class GLIBMM_API Variant<VariantBase> : public VariantContainerBase
463{
464  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
465  _CLASS_GENERIC(Variant<VariantBase>, GVariant)
466
467public:
468  using CType = GVariant*;
469  using CppType = VariantBase;
470  using CppContainerType = Variant<VariantBase>;
471
472  /// Default constructor.
473  Variant<VariantBase>();
474
475  /** GVariant constructor.
476   * @param castitem The GVariant to wrap.
477   * @param take_a_reference Whether to take an extra reference of the
478   * GVariant or not (not taking one could destroy the GVariant with the
479   * wrapper).
480   */
481  explicit Variant<VariantBase>(GVariant* castitem, bool take_a_reference = false);
482
483  /** Gets the VariantType.
484   * @return The VariantType.
485   * @newin{2,28}
486   */
487  static const VariantType& variant_type() G_GNUC_CONST;
488
489  //This must have a create() method because otherwise it would be a copy
490  //constructor.
491  /** Creates a new Variant<VariantBase>.
492   * @param data The value of the new Variant.
493   * @return The new Variant.
494   * @newin{2,28}
495   */
496  static Variant<VariantBase> create(const VariantBase& data);
497  _IGNORE(g_variant_new_variant)
498
499  //TODO: Documentation
500  void get(VariantBase& variant) const;
501
502  //TODO: Deprecate this in favour of get(VariantBase&)?
503  _WRAP_METHOD(VariantBase get() const, g_variant_get_variant)
504};
505
506/** Specialization of Variant containing a Variant<T>.
507 * Perhaps the main use of this is as a maybe-typed (i.e. nullable) Variant, as
508 * it inherits the methods create_maybe() and get_maybe() from
509 * VariantContainerBase, plus get_n_children() to allow checking whether there
510 * is a contained value, i.e. the inner Variant is not <tt>nothing</tt>.
511 *
512 * @newin{2,36}
513 * @ingroup Variant
514 */
515template<class T>
516class Variant< Variant<T> > : public VariantContainerBase
517{
518public:
519  using CType = GVariant*;
520  using CppType = Variant<T>;
521  using CppContainerType = Variant<CppType>;
522
523  /// Default constructor.
524  Variant< Variant<T> >();
525
526  /** GVariant constructor.
527   * @param castitem The GVariant to wrap.
528   * @param take_a_reference Whether to take an extra reference of the
529   * GVariant or not (not taking one could destroy the GVariant with the
530   * wrapper).
531   * @newin{2,36}
532   */
533  explicit Variant< Variant<T> >(GVariant* castitem, bool take_a_reference = false);
534
535  /** Gets the VariantType.
536   * @return The VariantType.
537   * @newin{2,36}
538   */
539  static const VariantType& variant_type() G_GNUC_CONST;
540
541  /** Creates a new Variant< Variant<T> >.
542   * @param data The value of the new Variant.
543   * @return The new Variant.
544   * @newin{2,36}
545   */
546  static Variant< Variant<T> > create(const Variant<T>& data);
547
548  /** Gets the contents of the Variant.
549   * @return The contents of the Variant.
550   * @newin{2,36}
551   */
552  Variant<T> get() const;
553};
554
555/** Specialization of Variant containing a Glib::ustring, for variants of type
556 * string, object path, or signature.
557 * @newin{2,28}
558 * @ingroup Variant
559 */
560template<>
561class GLIBMM_API Variant<Glib::ustring> : public VariantStringBase
562{
563  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
564  _CLASS_GENERIC(Variant<Glib::ustring>, GVariant)
565public:
566  using CType = char*;
567  using CppType = Glib::ustring;
568
569  /// Default constructor.
570  Variant<Glib::ustring>();
571
572  /** GVariant constructor.
573   * @param castitem The GVariant to wrap.
574   * @param take_a_reference Whether to take an extra reference of the
575   * GVariant or not (not taking one could destroy the GVariant with the
576   * wrapper).
577   */
578  explicit Variant<Glib::ustring>(GVariant* castitem,  bool take_a_reference = false);
579
580  /** Gets the VariantType.
581   * @return The VariantType.
582   * @newin{2,28}
583   */
584  static const VariantType& variant_type() G_GNUC_CONST;
585
586  /** Creates a new Variant<Glib::ustring>.
587   * @param data The value of the new Variant.
588   * @return The new Variant.
589   * @newin{2,28}
590   */
591  static Variant<Glib::ustring> create(const Glib::ustring& data);
592
593  //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter.
594  /** Gets the contents of the Variant.
595   * @return The contents of the Variant.
596   * @newin{2,28}
597   */
598  Glib::ustring get() const;
599  _IGNORE(g_variant_get_string, g_variant_dup_string)
600};
601
602//TODO: When we can break ABI, remove this template specialization.
603template<>
604GLIBMM_API Variant<Glib::ustring> VariantBase::cast_dynamic< Variant<Glib::ustring> >(const VariantBase& v);
605
606/** Specialization of Variant containing a Glib::DBusObjectPathString,
607 * for variants of type object path.
608 * @newin{2,54}
609 * @ingroup Variant
610 */
611template<>
612class GLIBMM_API Variant<Glib::DBusObjectPathString> : public VariantStringBase
613{
614  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
615  _CLASS_GENERIC(Variant<Glib::DBusObjectPathString>, GVariant)
616public:
617  using CType = char*;
618  using CppType = Glib::DBusObjectPathString;
619
620  /// Default constructor.
621  Variant();
622
623  /** GVariant constructor.
624   * @param castitem The GVariant to wrap.
625   * @param take_a_reference Whether to take an extra reference of the
626   * GVariant or not (not taking one could destroy the GVariant with the
627   * wrapper).
628   */
629  explicit Variant(GVariant* castitem,  bool take_a_reference = false);
630
631  /** Gets the VariantType.
632   * @return The VariantType.
633   * @newin{2,54}
634   */
635  static const VariantType& variant_type() G_GNUC_CONST;
636
637  /** Creates a new Variant<Glib::DBusObjectPathString>.
638   * @param data The value of the new Variant.
639   * @return The new Variant.
640   * @newin{2,54}
641   */
642  static Variant<CppType> create(const CppType& data);
643
644  //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter.
645  /** Gets the contents of the Variant.
646   * @return The contents of the Variant.
647   * @newin{2,54}
648   */
649  CppType get() const;
650};
651
652/** Specialization of Variant containing a Glib::DBusSignatureString,
653 * for variants of type signature.
654 * @newin{2,54}
655 * @ingroup Variant
656 */
657template<>
658class GLIBMM_API Variant<Glib::DBusSignatureString> : public VariantStringBase
659{
660  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
661  _CLASS_GENERIC(Variant<Glib::DBusSignatureString>, GVariant)
662public:
663  using CType = char*;
664  using CppType = Glib::DBusSignatureString;
665
666  /// Default constructor.
667  Variant();
668
669  /** GVariant constructor.
670   * @param castitem The GVariant to wrap.
671   * @param take_a_reference Whether to take an extra reference of the
672   * GVariant or not (not taking one could destroy the GVariant with the
673   * wrapper).
674   */
675  explicit Variant(GVariant* castitem,  bool take_a_reference = false);
676
677  /** Gets the VariantType.
678   * @return The VariantType.
679   * @newin{2,54}
680   */
681  static const VariantType& variant_type() G_GNUC_CONST;
682
683  /** Creates a new Variant<Glib::DBusSignatureString>.
684   * @param data The value of the new Variant.
685   * @return The new Variant.
686   * @newin{2,54}
687   */
688  static Variant<CppType> create(const CppType& data);
689
690  //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter.
691  /** Gets the contents of the Variant.
692   * @return The contents of the Variant.
693   * @newin{2,54}
694   */
695  CppType get() const;
696};
697
698/** Specialization of Variant containing a std::string, for variants of type
699 * bytestring, string, object path, or signature.
700 * See also Variant<Glib::ustring> for UTF-8 strings.
701 * @newin{2,28}
702 * @ingroup Variant
703 */
704template<>
705class GLIBMM_API Variant<std::string> : public VariantStringBase
706{
707  // Trick gmmproc into thinking this is derived from GVariant to wrap some methods.
708  _CLASS_GENERIC(Variant<std::string>, GVariant)
709public:
710  using CType = char*                ;
711  using CppType = std::string;
712
713  /// Default constructor.
714  Variant<std::string>();
715
716  /** GVariant constructor.
717   * @param castitem The GVariant to wrap.
718   * @param take_a_reference Whether to take an extra reference of the
719   * GVariant or not (not taking one could destroy the GVariant with the
720   * wrapper).
721   */
722  explicit Variant<std::string>(GVariant* castitem, bool take_a_reference = false);
723
724  /** Gets the VariantType.
725   * @return The VariantType.
726   * @newin{2,28}
727   */
728  static const VariantType& variant_type() G_GNUC_CONST;
729
730  /** Creates a new Variant<std::string>.
731   * @param data The value of the new Variant.
732   * @return The new Variant.
733   * @newin{2,28}
734   */
735  static Variant<std::string> create(const std::string& data);
736
737  //TODO: Documentation.
738  std::string get() const;
739  _IGNORE(g_variant_get_bytestring, g_variant_dup_bytestring)
740};
741
742//TODO: When we can break ABI, remove this template specialization.
743template<>
744GLIBMM_API Variant<std::string> VariantBase::cast_dynamic< Variant<std::string> >(const VariantBase& v);
745
746/** Specialization of Variant containing a dictionary entry.  See also
747 * Variant< std::map<K, V> >.
748 * @newin{2,28}
749 * @ingroup Variant
750 */
751template<class K, class V>
752class Variant< std::pair<K, V> > : public VariantContainerBase
753{
754public:
755  using CppType = std::pair<K, V>;
756  using CppContainerType = Variant<CppType>;
757
758  /// Default constructor.
759  Variant< std::pair<K, V> >()
760  : VariantContainerBase()
761  {}
762
763  /** GVariant constructor.
764   * @param castitem The GVariant to wrap.
765   * @param take_a_reference Whether to take an extra reference of the
766   * GVariant or not (not taking one could destroy the GVariant with the
767   * wrapper).
768   */
769  explicit Variant< std::pair<K, V> >(GVariant* castitem,
770    bool take_a_reference = false)
771  : VariantContainerBase(castitem, take_a_reference)
772  {}
773
774  /** Gets the VariantType.
775   * @return The VariantType.
776   * @newin{2,28}
777   */
778  static const VariantType& variant_type() G_GNUC_CONST;
779
780  /** Creates a new Variant< std::pair<K, V> >.
781   * @param data The value of the new Variant.
782   * @return The new Variant.
783   * @newin{2,28}
784   */
785  static Variant< std::pair<K, V> > create(const std::pair<K, V>& data);
786  _IGNORE(g_variant_new_dict_entry)
787
788  /** Gets the contents of the Variant.
789   * @return The contents of the Variant.
790   * @throw std::out_of_range
791   * @newin{2,28}
792   */
793  std::pair<K, V> get() const;
794};
795
796/** Specialization of Variant containing an array of items.
797 * @newin{2,28}
798 * @ingroup Variant
799 */
800template<class T>
801class Variant< std::vector<T> > : public VariantContainerBase
802{
803public:
804  using CppType = T                    ;
805  using CppContainerType = std::vector<T>;
806
807  /// Default constructor.
808  Variant< std::vector<T> >()
809  : VariantContainerBase()
810  {}
811
812  /** GVariant constructor.
813   * @param castitem The GVariant to wrap.
814   * @param take_a_reference Whether to take an extra reference of the
815   * GVariant or not (not taking one could destroy the GVariant with the
816   * wrapper).
817   */
818  explicit Variant< std::vector<T> >(GVariant* castitem,
819    bool take_a_reference = false)
820  : VariantContainerBase(castitem, take_a_reference)
821  {}
822
823  /** Gets the VariantType.
824   * @return The VariantType.
825   * @newin{2,28}
826   */
827  static const VariantType& variant_type() G_GNUC_CONST;
828
829  /** Creates a new Variant from an array of numeric types.
830   * @param data The array to use for creation.
831   * @return The new Variant.
832   * @newin{2,28}
833   */
834  static Variant< std::vector<T> > create(const std::vector<T>& data);
835  _IGNORE(g_variant_new_array)
836
837  /** Gets a specific element of the array.  It is an error if @a index is
838   * greater than the number of child items in the container.  See
839   * VariantContainerBase::get_n_children().
840   *
841   * This function is O(1).
842   *
843   * @param index The index of the element.
844   * @return The element at index @a index.
845   * @throw std::out_of_range
846   * @newin{2,28}
847   */
848  T get_child(gsize index) const;
849
850  /** Gets the vector of the Variant.
851   * @return The vector.
852   * @newin{2,28}
853   */
854  std::vector<T> get() const;
855  _IGNORE(g_variant_get_fixed_array)
856
857  /** Gets a VariantIter of the Variant.
858   * @return the VariantIter.
859   * @newin{2,28}
860   */
861  VariantIter get_iter() const;
862};
863
864/** Specialization of Variant containing an array of UTF-8 capable
865 * strings.
866 * @newin{2,28}
867 * @ingroup Variant
868 */
869template<>
870class GLIBMM_API Variant< std::vector<Glib::ustring> > : public VariantContainerBase
871{
872public:
873  using CppType = Glib::ustring                ;
874  using CppContainerType = std::vector<Glib::ustring>;
875
876  /// Default constructor.
877  Variant< std::vector<Glib::ustring> >();
878
879  /** GVariant constructor.
880   * @param castitem The GVariant to wrap.
881   * @param take_a_reference Whether to take an extra reference of the
882   * GVariant or not (not taking one could destroy the GVariant with the
883   * wrapper).
884   */
885  explicit Variant< std::vector<Glib::ustring> >(GVariant* castitem, bool take_a_reference = false);
886
887  /** Gets the VariantType.
888   * @return The VariantType.
889   * @newin{2,28}
890   */
891  static const VariantType& variant_type() G_GNUC_CONST;
892
893  /** Creates a new Variant from an array of strings.
894   * @param data The array to use for creation.
895   * @return The new Variant.
896   * @newin{2,28}
897   */
898  static Variant< std::vector<Glib::ustring> >
899    create(const std::vector<Glib::ustring>& data);
900
901  /** Gets a specific element of the string array.  It is an error if @a index
902   * is greater than the number of child items in the container.  See
903   * VariantContainerBase::get_n_children().
904   *
905   * This function is O(1).
906   *
907   * @param index The index of the element.
908   * @return The element at index @a index.
909   * @throw std::out_of_range
910   * @newin{2,28}
911   */
912  Glib::ustring get_child(gsize index) const;
913
914  /** Gets the string vector of the Variant.
915   * @return The vector.
916   * @newin{2,28}
917   */
918  std::vector<Glib::ustring> get() const;
919  _IGNORE(g_variant_get_strv, g_variant_dup_strv)
920
921  /** Gets a VariantIter of the Variant.
922   * @return the VariantIter.
923   * @newin{2,28}
924   */
925  VariantIter get_iter() const;
926};
927
928/** Specialization of Variant containing an array of D-Bus object paths.
929 *
930 * @newin{2,54}
931 * @ingroup Variant
932 */
933template<>
934class GLIBMM_API Variant<std::vector<Glib::DBusObjectPathString>> : public VariantContainerBase
935{
936public:
937  using CppType = Glib::DBusObjectPathString;
938  using CppContainerType = std::vector<Glib::DBusObjectPathString>;
939
940  /// Default constructor.
941  Variant();
942
943  /** GVariant constructor.
944   * @param castitem The GVariant to wrap.
945   * @param take_a_reference Whether to take an extra reference of the
946   * GVariant or not (not taking one could destroy the GVariant with the
947   * wrapper).
948   */
949  explicit Variant(GVariant* castitem, bool take_a_reference = false);
950
951  /** Gets the VariantType.
952   * @return The VariantType.
953   * @newin{2,54}
954   */
955  static const VariantType& variant_type() G_GNUC_CONST;
956
957  /** Creates a new Variant from an array of strings.
958   * @param data The array to use for creation.
959   * @return The new Variant.
960   * @newin{2,54}
961   */
962  static Variant<CppContainerType> create(const CppContainerType& data);
963
964  /** Gets a specific element of the string array.  It is an error if @a index
965   * is greater than the number of child items in the container.  See
966   * VariantContainerBase::get_n_children().
967   *
968   * This function is O(1).
969   *
970   * @param index The index of the element.
971   * @return The element at index @a index.
972   * @throw std::out_of_range
973   * @newin{2,54}
974   */
975  CppType get_child(gsize index) const;
976
977  /** Gets the string vector of the Variant.
978   * @return The vector.
979   * @newin{2,54}
980   */
981  CppContainerType get() const;
982
983  /** Gets a VariantIter of the Variant.
984   * @return the VariantIter.
985   * @newin{2,54}
986   */
987  VariantIter get_iter() const;
988};
989
990/** Specialization of Variant containing an array of non-UTF-8 strings
991 * (byte string arrays).
992 * @newin{2,28}
993 * @ingroup Variant
994 */
995template<>
996class GLIBMM_API Variant< std::vector<std::string> > : public VariantContainerBase
997{
998public:
999  using CppType = std::string                  ;
1000  using CppContainerType = std::vector<std::string>;
1001
1002  /// Default constructor.
1003  Variant< std::vector<std::string> >();
1004
1005  /** GVariant constructor.
1006   * @param castitem The GVariant to wrap.
1007   * @param take_a_reference Whether to take an extra reference of the
1008   * GVariant or not (not taking one could destroy the GVariant with the
1009   * wrapper).
1010   */
1011  explicit Variant< std::vector<std::string> >(GVariant* castitem, bool take_a_reference = false);
1012
1013  /** Gets the VariantType.
1014   * @return The VariantType.
1015   * @newin{2,28}
1016   */
1017  static const VariantType& variant_type() G_GNUC_CONST;
1018
1019  /** Creates a new Variant from an array of strings.
1020   * @param data The array to use for creation.
1021   * @return The new Variant.
1022   * @newin{2,28}
1023   */
1024  static Variant< std::vector<std::string> >
1025    create(const std::vector<std::string>& data);
1026
1027  /** Creates a new Variant from an array of D-Bus object paths.
1028   * @param paths The array to use for creation.
1029   * @return The new Variant.
1030   * @newin{2,36}
1031   */
1032  static Variant< std::vector<std::string> >
1033    create_from_object_paths(const std::vector<std::string>& paths);
1034
1035  /** Gets a specific element of the string array.  It is an error if @a index
1036   * is greater than the number of child items in the container.  See
1037   * VariantContainerBase::get_n_children().
1038   *
1039   * This function is O(1).
1040   *
1041   * @param index The index of the element.
1042   * @return The element at index @a index.
1043   * @throw std::out_of_range
1044   * @newin{2,28}
1045   */
1046  std::string get_child(gsize index) const;
1047
1048  /** Gets the string vector of the Variant.
1049   * @return The vector.
1050   * @newin{2,28}
1051   */
1052  std::vector<std::string> get() const;
1053  _IGNORE(g_variant_get_bytestring_array, g_variant_dup_bytestring_array)
1054
1055  // Object paths are merely strings so it is possible to get them already with
1056  // the existing get() methods in this class.
1057  _IGNORE(g_variant_get_objv, g_variant_dup_objv)
1058
1059  /** Gets a VariantIter of the Variant.
1060   * @return the VariantIter.
1061   * @newin{2,28}
1062   */
1063  VariantIter get_iter() const;
1064};
1065
1066/** Specialization of Variant containing a dictionary (a map of (key,
1067 * value) elements).
1068 * @newin{2,28}
1069 * @ingroup Variant
1070 */
1071template<class K, class V>
1072class Variant< std::map<K, V> >: public VariantContainerBase
1073{
1074public:
1075  using CppType = std::pair<K, V>;
1076  using CppContainerType = std::map<K, V>;
1077
1078  /// Default constructor.
1079  Variant< std::map<K, V> >()
1080  : VariantContainerBase()
1081  {}
1082
1083  /** GVariant constructor.
1084   * @param castitem The GVariant to wrap.
1085   * @param take_a_reference Whether to take an extra reference of the
1086   * GVariant or not (not taking one could destroy the GVariant with the
1087   * wrapper).
1088   */
1089  explicit Variant< std::map<K, V> >(GVariant* castitem,
1090    bool take_a_reference = false)
1091  : VariantContainerBase(castitem, take_a_reference)
1092  {}
1093
1094  /** Gets the VariantType.
1095   * @return The VariantType.
1096   * @newin{2,28}
1097   */
1098  static const VariantType& variant_type() G_GNUC_CONST;
1099
1100  /** Creates a new Variant containing a dictionary from a map.
1101   * @param data The map to use for creation.
1102   * @return The new Variant holding a dictionary.
1103   * @newin{2,28}
1104   */
1105  static Variant< std::map<K, V> > create(const std::map<K, V>& data);
1106
1107  /** Gets a specific dictionary entry from the string array.  It is an error
1108   * if @a index is greater than the number of child items in the container.
1109   * See VariantContainerBase::get_n_children().
1110   *
1111   * This function is O(1).
1112   *
1113   * @param index The index of the element.
1114   * @return The dictionary entry at index @a index.
1115   * @throw std::out_of_range
1116   * @newin{2,28}
1117   */
1118  std::pair<K, V> get_child(gsize index) const;
1119
1120  /** Looks up a value in a dictionary Variant.
1121   * @param key The key to look up.
1122   * @param value A location in which to store the value if found.
1123   * @return <tt>true</tt> if the key is found, <tt>false</tt> otherwise.
1124   */
1125  bool lookup(const K& key, V& value) const;
1126  _IGNORE(g_variant_lookup_value, g_variant_lookup)
1127
1128  /** Gets the map (the dictionary) of the Variant.
1129   * @return The vector.
1130   * @newin{2,28}
1131   */
1132  std::map<K, V> get() const;
1133
1134  /** Gets a VariantIter of the Variant.
1135   * @return the VariantIter.
1136   * @newin{2,28}
1137   */
1138  VariantIter get_iter() const;
1139};
1140
1141/** Specialization of Variant containing a tuple.
1142 * @newin{2,54}
1143 * @ingroup Variant
1144 */
1145template <class... Types>
1146class Variant<std::tuple<Types...>> : public VariantContainerBase
1147{
1148public:
1149  using CppContainerType = std::tuple<Types...>;
1150
1151  /// Default constructor
1152  Variant<std::tuple<Types...>>()
1153  : VariantContainerBase()
1154  {}
1155
1156  /** GVariant constructor.
1157   * @param castitem The GVariant to wrap.
1158   * @param take_a_reference Whether to take an extra reference of the GVariant
1159   *        or not (not taking one could destroy the GVariant with the wrapper).
1160   */
1161  explicit Variant<std::tuple<Types...>>(GVariant* castitem, bool take_a_reference = false)
1162  : VariantContainerBase(castitem, take_a_reference)
1163  {}
1164
1165  /** Creates a new Variant containing a tuple.
1166   * @param data The tuple to use for creation.
1167   * @return The new Variant holding a tuple.
1168   * @newin{2,54}
1169   */
1170  static Variant<std::tuple<Types...>> create(const std::tuple<Types...>& data);
1171
1172  /** Gets the VariantType.
1173   * @return The VariantType.
1174   * @newin{2,54}
1175   */
1176  static const VariantType& variant_type() G_GNUC_CONST;
1177
1178  /** Gets a specific element from the tuple.
1179   * It is an error if @a index is greater than or equal to the number of
1180   * elements in the tuple. See VariantContainerBase::get_n_children().
1181   *
1182   * @param index The index of the element.
1183   * @return The tuple element at index @a index.
1184   * @throw std::out_of_range
1185   * @newin{2,54}
1186   */
1187  template<class T>
1188  T get_child(gsize index) const;
1189
1190  template<class T>
1191  Variant<T> get_child_variant(gsize index) const;
1192
1193  /** Gets the tuple of the Variant.
1194   * @return The tuple.
1195   * @newin{2,54}
1196   */
1197  std::tuple<Types...> get() const;
1198
1199  /** Gets a VariantIter of the Variant.
1200   * @return The VariantIter.
1201   * @newin{2,54}
1202   */
1203  VariantIter get_iter() const;
1204};
1205
1206} // namespace Glib
1207
1208
1209//We ignore g_variant_get_*() methods that are wrapped by Variant<> specializations, such as in variant_basictypes.h.m4.
1210_IGNORE(
1211  g_variant_get_boolean,
1212  g_variant_get_byte,
1213  g_variant_get_int16,
1214  g_variant_get_uint16,
1215  g_variant_get_int32,
1216  g_variant_get_handle,
1217  g_variant_get_uint32,
1218  g_variant_get_int64,
1219  g_variant_get_uint64,
1220  g_variant_get_double,
1221  g_variant_iter_new
1222)
1223
1224/* Include generated specializations of Variant<> for fundamental types:
1225 */
1226#define _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H
1227#include <glibmm/variant_basictypes.h>
1228#undef _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H
1229
1230namespace Glib
1231{
1232
1233/*--------------------Variant< Variant<T> >---------------------*/
1234
1235template<class T>
1236Variant< Variant<T> >::Variant()
1237: VariantContainerBase()
1238{
1239}
1240
1241template<class T>
1242Variant< Variant<T> >::Variant(GVariant* castitem, bool take_a_reference)
1243: VariantContainerBase(castitem, take_a_reference)
1244{
1245}
1246
1247// static
1248template<class T>
1249const VariantType& Variant< Variant<T> >::variant_type()
1250{
1251  return VARIANT_TYPE_VARIANT;
1252}
1253
1254template<class T>
1255Variant< Variant<T> > Variant< Variant<T> >::create(const Variant<T>& data)
1256{
1257  Variant< Variant<T> > result = Variant< Variant<T> >(
1258    g_variant_new_variant(const_cast<GVariant*>(data.gobj())));
1259  return result;
1260}
1261
1262template<class T>
1263Variant<T> Variant< Variant<T> >::get() const
1264{
1265  GVariant* const gvariant = g_variant_get_variant(gobject_);
1266  return Variant<T>(gvariant);
1267}
1268
1269/*--------------------Variant< std::pair<K, V> >---------------------*/
1270
1271// static
1272template<class K, class V>
1273const VariantType& Variant< std::pair<K, V> >::variant_type()
1274{
1275  static VariantType type(
1276    g_variant_type_new_dict_entry(Variant<K>::variant_type().gobj(),
1277    Variant<V>::variant_type().gobj()));
1278
1279  return type;
1280}
1281
1282template<class K, class V>
1283Variant< std::pair<K, V> >
1284Variant< std::pair<K, V> >::create(const std::pair<K, V>& data)
1285{
1286  Variant<K> key = Variant<K>::create(data.first);
1287  Variant<V> value = Variant<V>::create(data.second);
1288
1289  Variant< std::pair<K, V> > result = Variant< std::pair<K, V> >(
1290    g_variant_new_dict_entry(key.gobj(), value.gobj()));
1291
1292  return result;
1293}
1294
1295template<class K, class V>
1296std::pair<K, V> Variant< std::pair<K, V> >::get() const
1297{
1298  // Get the key (the first element of this VariantContainerBase).
1299  Variant<K> key;
1300  VariantContainerBase::get_child(key, 0);
1301
1302  // Get the value (the second element of this VariantContainerBase).
1303  Variant<V> value;
1304  VariantContainerBase::get_child(value, 1);
1305
1306  std::pair<K, V> result(key.get(), value.get());
1307
1308  return result;
1309}
1310
1311/*---------------------Variant< std::vector<T> >---------------------*/
1312
1313// static
1314template<class T>
1315const VariantType& Variant< std::vector<T> >::variant_type()
1316{
1317  static VariantType type =
1318    VariantType::create_array(Variant<T>::variant_type());
1319
1320  return type;
1321}
1322
1323template<class T>
1324Variant< std::vector<T> >
1325Variant< std::vector<T> >::create(const std::vector<T>& data)
1326{
1327  // Get the variant type of the array.
1328  VariantType array_variant_type = Variant< std::vector<T> >::variant_type();
1329
1330  // Create a GVariantBuilder to build the array.
1331  GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj());
1332
1333  // Add the elements of the vector into the builder.
1334  for(const auto& element : data)
1335  {
1336    Glib::Variant<T> variant = Glib::Variant<T>::create(element);
1337    g_variant_builder_add_value(builder, variant.gobj());
1338  }
1339
1340  // Create the variant using the builder.
1341  Variant< std::vector<T> > result =
1342    Variant< std::vector<T> >(g_variant_new(
1343      reinterpret_cast<const gchar*>(array_variant_type.gobj()), builder));
1344
1345  g_variant_builder_unref(builder);
1346
1347  return result;
1348}
1349
1350template<class T>
1351T Variant< std::vector<T> >::get_child(gsize index) const
1352{
1353  if (index >= get_n_children())
1354    throw std::out_of_range(
1355      "Variant< std::vector<T> >::get_child(): Index out of bounds.");
1356
1357  Glib::Variant<T> variant;
1358
1359  GVariant* gvariant =
1360    g_variant_get_child_value(const_cast<GVariant*>(gobj()), index);
1361
1362  variant.init(gvariant);
1363  return variant.get();
1364}
1365
1366template<class T>
1367std::vector<T> Variant< std::vector<T> >::get() const
1368{
1369  std::vector<T> result;
1370
1371  for (gsize i = 0, n_children = get_n_children(); i < n_children; ++i)
1372  {
1373    Glib::Variant<T> variant;
1374
1375    GVariant* gvariant =
1376      g_variant_get_child_value(const_cast<GVariant*>(gobj()), i);
1377
1378    variant.init(gvariant);
1379    result.emplace_back(variant.get());
1380  }
1381
1382  return result;
1383}
1384
1385template<class T>
1386VariantIter Variant< std::vector<T> >::get_iter() const
1387{
1388  return VariantContainerBase::get_iter(variant_type());
1389}
1390
1391/*---------------------Variant< std::map<K, V> > --------------------*/
1392
1393// static
1394template<class K, class V>
1395const VariantType& Variant< std::map<K, V> >::variant_type()
1396{
1397  static VariantType type =
1398    VariantType::create_array(Variant< std::pair<K, V> >::variant_type());
1399
1400  return type;
1401}
1402
1403template<class K, class V>
1404Variant< std::map<K, V> >
1405Variant< std::map<K, V> >::create(const std::map<K, V>& data)
1406{
1407  // Get the variant type of the elements.
1408  VariantType element_variant_type =
1409    Variant< std::pair<K, V> >::variant_type();
1410
1411  // Get the variant type of the array.
1412  VariantType array_variant_type = Variant< std::map<K, V> >::variant_type();
1413
1414  // Create a GVariantBuilder to build the array.
1415  GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj());
1416
1417  // Add the elements of the map into the builder.
1418  for(const auto& element : data)
1419  {
1420    auto dict_entry =
1421      Variant< std::pair<K, V> >::create(element);
1422
1423    g_variant_builder_add_value(builder, dict_entry.gobj());
1424  }
1425
1426  // Create the variant using the builder.
1427  Variant< std::map<K, V> > result = Variant< std::map<K, V> >(g_variant_new(
1428    reinterpret_cast<const gchar*>(array_variant_type.gobj()), builder));
1429
1430  g_variant_builder_unref(builder);
1431
1432  return result;
1433}
1434
1435template<class K, class V>
1436std::pair<K, V>
1437Variant< std::map<K, V> >::get_child(gsize index) const
1438{
1439  Variant< std::pair<K, V> > dict_entry;
1440  VariantContainerBase::get_child(dict_entry, index);
1441  return dict_entry.get();
1442}
1443
1444template<class K, class V>
1445bool Variant< std::map<K, V> >::lookup(const K& key, V& value) const
1446{
1447  // The code in this method pretty much reflects the g_variant_lookup_value()
1448  // function except that it's more general to deal with keys that are not
1449  // just strings.
1450  VariantIter iter = get_iter();
1451
1452  Variant< std::pair<K, V> > entry;
1453
1454  while(iter.next_value(entry))
1455  {
1456    std::pair<K, V> element = entry.get();
1457
1458    if(element.first == key)
1459    {
1460      value = element.second;
1461      return true;
1462    }
1463  }
1464
1465  return false;
1466}
1467
1468template<class K, class V>
1469std::map<K, V> Variant< std::map<K, V> >::get() const
1470{
1471  std::map<K, V> result;
1472  VariantIter iter = get_iter();
1473  Variant< std::pair<K, V> > entry;
1474
1475  while(iter.next_value(entry))
1476  {
1477    result.insert(entry.get());
1478  }
1479
1480  return result;
1481}
1482
1483template<class K, class V>
1484VariantIter Variant< std::map<K, V> >::get_iter() const
1485{
1486  return VariantContainerBase::get_iter(variant_type());
1487}
1488
1489/*---------------------Variant<std::tuple<class... Types>> --------------------*/
1490
1491// static
1492template <class... Types>
1493const VariantType& Variant<std::tuple<Types...>>::variant_type()
1494{
1495  std::vector<VariantType> types;
1496  auto expander = [&types](const VariantType &type) mutable -> int
1497  {
1498    types.push_back(type);
1499    return 0;
1500  };
1501
1502  // expands the variadic template parameters
1503  using swallow = int[]; // ensures left to right order
1504  (void)swallow{(expander(Variant<Types>::variant_type()))...};
1505  static auto type = VariantType::create_tuple(types);
1506
1507  return type;
1508}
1509
1510#ifndef DOXYGEN_SHOULD_SKIP_THIS
1511namespace detail
1512{
1513// std::index_sequence and std::index_sequence_for are new in C++14,
1514// but this version of glibmm requires only C++11.
1515// The following code replaces std::index_sequence and std::index_sequence_for
1516// until we can require C++14 support.
1517// See https://bugzilla.gnome.org/show_bug.cgi?id=787648
1518
1519  /// Class template integer_sequence
1520  template<typename T, T... Idx>
1521    struct integer_sequence
1522    {
1523      typedef T value_type;
1524      static constexpr std::size_t size() { return sizeof...(Idx); }
1525    };
1526
1527  // Concatenates two integer_sequences.
1528  template<typename Iseq1, typename Iseq2> struct iseq_cat;
1529
1530  template<typename T, std::size_t... Ind1, std::size_t... Ind2>
1531    struct iseq_cat<integer_sequence<T, Ind1...>, integer_sequence<T, Ind2...>>
1532    {
1533      using type = integer_sequence<T, Ind1..., (Ind2 + sizeof...(Ind1))...>;
1534    };
1535
1536  // Builds an integer_sequence<T, 0, 1, 2, ..., Num-1>.
1537  template<typename T, std::size_t Num>
1538    struct make_intseq
1539    : iseq_cat<typename make_intseq<T, Num / 2>::type,
1540		typename make_intseq<T, Num - Num / 2>::type>
1541    { };
1542
1543  template<typename T>
1544    struct make_intseq<T, 1>
1545    {
1546      typedef integer_sequence<T, 0> type;
1547    };
1548
1549  template<typename T>
1550    struct make_intseq<T, 0>
1551    {
1552      typedef integer_sequence<T> type;
1553    };
1554
1555  /// Alias template make_integer_sequence
1556  template<typename T, T Num>
1557    using make_integer_sequence = typename make_intseq<T, Num>::type;
1558
1559  /// Alias template index_sequence
1560  template<std::size_t... Idx>
1561    using index_sequence = integer_sequence<std::size_t, Idx...>;
1562
1563  /// Alias template make_index_sequence
1564  template<std::size_t Num>
1565    using make_index_sequence = make_integer_sequence<std::size_t, Num>;
1566
1567  /// Alias template index_sequence_for
1568  template<typename... Types>
1569    using index_sequence_for = make_index_sequence<sizeof...(Types)>;
1570
1571// End of code that replaces std::index_sequence and std::index_sequence_for
1572
1573template <class Tuple, std::size_t... Is>
1574void expand_tuple(std::vector<VariantBase> &variants, const Tuple & t,
1575                  detail::index_sequence<Is...>)
1576{
1577  using swallow = int[]; // ensures left to right order
1578  auto expander = [&variants](const VariantBase &variant) -> int
1579  {
1580    variants.push_back(variant);
1581    return 0;
1582  };
1583  (void)swallow {(expander(Variant<typename std::tuple_element<Is, Tuple>::type>::create(std::get<Is>(t))))...};
1584}
1585} // namespace detail
1586#endif // DOXYGEN_SHOULD_SKIP_THIS
1587
1588template <class... Types>
1589Variant<std::tuple<Types...>>
1590Variant<std::tuple<Types...>>::create(const std::tuple<Types...>& data)
1591{
1592  // create a vector containing all tuple values as variants
1593  std::vector<Glib::VariantBase> variants;
1594  detail::expand_tuple(variants, data, detail::index_sequence_for<Types...>{});
1595
1596  using var_ptr = GVariant*;
1597  std::unique_ptr<var_ptr[]> var_array(new var_ptr[sizeof... (Types)]);
1598
1599  for (std::vector<VariantBase>::size_type i = 0; i < variants.size(); i++)
1600    var_array[i] = const_cast<GVariant*>(variants[i].gobj());
1601
1602  Variant<std::tuple<Types...>> result = Variant<std::tuple<Types...>>(
1603          g_variant_new_tuple(var_array.get(), variants.size()));
1604
1605  return result;
1606}
1607
1608template <class... Types>
1609template <class T>
1610T Variant<std::tuple<Types...>>::get_child(gsize index) const
1611{
1612  Variant<T> entry;
1613  VariantContainerBase::get_child(entry, index);
1614  return entry.get();
1615}
1616
1617template <class... Types>
1618template <class T>
1619Variant<T> Variant<std::tuple<Types...>>::get_child_variant(gsize index) const
1620{
1621  Variant<T> entry;
1622  VariantContainerBase::get_child(entry, index);
1623  return entry;
1624}
1625
1626#ifndef DOXYGEN_SHOULD_SKIP_THIS
1627namespace detail
1628{
1629// swallows any argument
1630template <class T>
1631constexpr int any_arg(T&& /* arg */)
1632{
1633  return 0;
1634}
1635
1636template <class Tuple, std::size_t... Is>
1637void assign_tuple(std::vector<VariantBase> &variants, Tuple & t, detail::index_sequence<Is...>)
1638{
1639  int i = 0;
1640  using swallow = int[]; // ensures left to right order
1641  (void)swallow {(any_arg(std::get<Is>(t) = VariantBase::cast_dynamic<Variant<typename std::tuple_element<Is, Tuple>::type > >(variants[i++]).get()))...};
1642}
1643} // namespace detail
1644#endif // DOXYGEN_SHOULD_SKIP_THIS
1645
1646template <class... Types>
1647std::tuple<Types...> Variant<std::tuple<Types...>>::get() const
1648{
1649  std::tuple<Types...> data;
1650  int i = 0;
1651
1652  std::vector<VariantBase> variants;
1653  using swallow = int[]; // ensures left to right order
1654  auto expander = [&variants, &i](const VariantBase &variant) -> int
1655  {
1656    variants.push_back(variant);
1657    return i++;
1658  };
1659  (void)swallow{(expander(get_child_variant<Types>(i)))...};
1660  detail::assign_tuple(variants, data, detail::index_sequence_for<Types...>{});
1661
1662  return data;
1663}
1664
1665template< class... Types>
1666VariantIter Variant<std::tuple<Types...>>::get_iter() const
1667{
1668  const auto type = variant_type();
1669  return VariantContainerBase::get_iter(type);
1670}
1671
1672#ifndef DOXYGEN_SHOULD_SKIP_THIS
1673// This is needed so Glib::VariantBase can be used with
1674// Glib::Value and _WRAP_PROPERTY in Gio::Action and elsewhere.
1675template <>
1676class GLIBMM_API Value<Glib::VariantBase> : public ValueBase_Variant
1677{
1678public:
1679  using CppType = Glib::VariantBase;
1680
1681  void set(CppType data);
1682  CppType get() const;
1683};
1684#endif /* DOXYGEN_SHOULD_SKIP_THIS */
1685
1686} // namespace Glib
1687