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

1152 questions
154
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,409
  • 5
  • 20
  • 28
47
votes
14 answers

Android Studio: No build variant found error

i am new to android development, i started developing from scratch on a project i bought online, following the documentation, i encountered a error saying No variants found for 'app'. Check build files to ensure at least one variant exists. Here is…
46
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
  • 60,273
  • 18
  • 132
  • 202
36
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
  • 400
  • 1
  • 3
  • 7
34
votes
2 answers

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
  • 1,002
  • 10
  • 18
34
votes
3 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) {…
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
  • 29,101
  • 5
  • 23
  • 50
32
votes
3 answers

std::variant reflection. How can I tell which type of value std::variant is assigned?

I have a class called foo_t that has a member called bar which could be any one of the types std::string, int, std::vector, etc. I would like to be able to ask foo_t which type bar has been assigned to. I decided to use std::variant. I've…
dhoodlum
  • 1,103
  • 2
  • 9
  • 18
31
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
  • 90,666
  • 33
  • 258
  • 416
30
votes
2 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,490
  • 1
  • 13
  • 22
30
votes
5 answers

How do I represent an Optional String in Go?

I wish to model a value which can have two possible forms: absent, or a string. The natural way to do this is with Maybe String, or Optional, or string option, etc. However, Go does not have variant types like this. I then thought, following…
jameshfisher
  • 34,029
  • 31
  • 121
  • 167
27
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
  • 1,003
  • 1
  • 9
  • 22
26
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,731
  • 1
  • 30
  • 46
26
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,330
  • 15
  • 26
25
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…
Denis Yaroshevskiy
  • 1,218
  • 11
  • 24
1
2 3
76 77