Questions tagged [variant]

A variant data type is a tagged union that holds other data types. It is a standard data type in [ocaml], and typically used for interop calls between languages ([c++] and [vb6]) in classic Microsoft Windows [com] programming. It also exists in other languages using other names, such as [discriminated-unions] or the more general concept of [algebraic-data-types]

In , the variant type is a basic building block of the language. Custom variants are defined with a set of constructors that restrict which types it can hold, and are used to inspect it in and to warn if a pattern match does not cover all constructors.

Questions that should have this tag would include ones involving how to pass data between Windows processes or within the same process using and classic function calls. Often the calls occur between languages (e.g. to ), but they are also used in single language programs (e.g. ) to achieve a plug-in, modular architecture with DLL files.

A variant is technically a structure holding a union of data types along with a VARTYPE that indicates which member of the structure is valid. It can hold any other data type, including primitive types (BYTE, LONG), pointers to primitive types (LONG*, FLOAT*), IDispatch pointers, and even pointers to other variants.

There are a couple of helper classes Microsoft has created to help with the details of dealing with raw variants:

These classes relieve much of the grunt work of interop programming with variants such as doing deep destroys on contained SAFEARRAYs.

Definitions

  • Tagged union: A data structure that can be used to hold a number of different data types, only one of which is valid at a time. There is a field (VARTYPE) which indicates the valid data member (https://en.wikipedia.org/wiki/Tagged_union)

Examples

OCaml

(* Definition of the built-in option type *)
type 'a option =
| Some of 'a
| None

(* Construction *)
let var = Some "hello"

(* Inspection through pattern matching *)
let greeting =
  match var with
  | Some str -> str
  | None -> "howdy"

Visual Basic

Dim var as Variant

var = "hello"   'Variant holds a string

var = 7         'Variant holds an Integer

C++

_variant_t var;

var = "hello";  //Variant holds a string

var = 7;        //Variant holds an int

Resources

Related tags

938 questions
150
votes
6 answers

How can mixed data types (int, float, char, etc) be stored in an array?

I want to store mixed data types in an array. How could one do that?
chanzerre
  • 2,309
  • 4
  • 16
  • 27
43
votes
10 answers

How is duck typing different from the old 'variant' type and/or interfaces?

I keep seeing the phrase "duck typing" bandied about, and even ran across a code example or two. I am way too lazy busy to do my own research, can someone tell me, briefly: the difference between a 'duck type' and an old-skool 'variant type', and…
Steven A. Lowe
  • 58,325
  • 18
  • 127
  • 199
33
votes
1 answer

Variable iterating on itself - different behavior with different types

Please take a look at the latest updates at the end of the post. In Particular, see Update 4: the Variant comparison Curse I’ve already seen mates banging their head against the wall to understand how a variant works, but never imagined that I will…
A.S.H
  • 28,433
  • 5
  • 19
  • 45
32
votes
2 answers

How to make a safer C++ variant visitor, similar to switch statements?

The pattern that a lot of people use with C++17 / boost variants looks very similar to switch statements. For example: (snippet from cppreference.com) std::variant v = ...; std::visit(overloaded { [](auto arg) {…
30
votes
10 answers

How to return the number of dimensions of a (Variant) variable passed to it in VBA

Does anyone know how to return the number of dimensions of a (Variant) variable passed to it in VBA?
user533978
  • 340
  • 1
  • 3
  • 7
29
votes
3 answers

What is idiomatic modern C++ for algebraic data types?

Suppose, for example, you want to implement a spreadsheet Cell in C++. A cell can be either a string, a number, or perhaps empty. Ignore other cases, like it being a formula. In Haskell, you might do something like: data Cell = CellStr String |…
blippy
  • 1,270
  • 1
  • 10
  • 16
27
votes
3 answers

Using std::visit on a class inheriting from std::variant - libstdc++ vs libc++

Consider the following code snippet: struct v : std::variant> { }; int main() { std::visit([](auto){ }, v{0}); } clang++ 7 with -stdlib=libc++ -std=c++2a compiles the code; g++ 9 with -std=c++2a fails to compile the code,…
Vittorio Romeo
  • 82,972
  • 25
  • 221
  • 369
25
votes
4 answers

Can't use c++17 features using g++ 7.2 in QtCreator

I have recently updated gcc and g++ to version 7.2. I would like to try out std::experimental::any and std::variant in particular, and I am using Qt 5.9.1 in QtCreator. So far I have written this in the project file: CONFIG += c++17 And I have…
Iron Attorney
  • 862
  • 1
  • 8
  • 19
25
votes
1 answer

get for variants fail under clang++ but not g++

The following code: variant x = "abc"; cout << get(x) << "\n"; works fine under g++ (version 7.2). However, when compiled under clang++ (version 5.0) using libstdc++, I get the following error in the get…
André Wagner
  • 1,190
  • 13
  • 25
24
votes
5 answers

Is there an existing name for this type and function?

There are 2 hard problems in computer science: cache invalidation, naming things and off-by-one errors. This is about the 2nd problem: naming things. I'm looking if this technique or type has been used somewhere else already and has a name. …
Yakk - Adam Nevraumont
  • 235,777
  • 25
  • 285
  • 465
23
votes
3 answers

Can't stream std::endl with overloaded operator<<() for std::variant

This answer describes how to stream a standalone std::variant. However, it doesn't seem to work when std::variant is stored in a std::unordered_map. The following example: #include #include #include #include…
Dev Null
  • 4,046
  • 1
  • 19
  • 40
23
votes
4 answers

Why std::get for variant throws on failure instead of being undefined behaviour?

According to cppreference std::get for variant throws std::bad_variant_access if the type contained in the variant is not the expected one. This means that the standard library has to check on every access (libc++). What was the rationale for this…
22
votes
2 answers

Why does std::visit take a variable number of variants?

Trying to get more familiar with C++17, I've just noticed std::visit: template constexpr /*something*/ visit(Visitor&& vis, Variants&&... vars); Why does std::visit not take a single variant, but rather any number…
einpoklum
  • 86,754
  • 39
  • 223
  • 453
22
votes
5 answers

How to store variant data in C++

I'm in the process of creating a class that stores metadata about a particular data source. The metadata is structured in a tree, very similar to how XML is structured. The metadata values can be integer, decimal, or string values. I'm curious if…
Perculator
  • 1,063
  • 1
  • 9
  • 12
20
votes
1 answer

Why are references forbidden in std::variant?

I use boost::variant a lot and am quite familiar with it. boost::variant does not restrict the bounded types in any way, in particular, they may be references: #include #include int main() { int x = 3; …
olq_plo
  • 627
  • 6
  • 16
1
2 3
62 63