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
6
votes
1 answer

A std::visit-like function for visiting over polymorphic types

I've been recently trying C++17's std::variant and std::visit, and I found it quite powerful. I specially liked the ability to create a visitor pattern over several variant objects. Here is one example of what I mean: std::variant
jesusbriales
  • 357
  • 1
  • 9
6
votes
1 answer

Clang claims constexpr member of generic lambda argument is not constexpr

I would like to write a generic lambda as a visitor for a variant. The members of this variant contain a constexpr member value, which I would like to use in the visitor. For example: #include template struct S { constexpr…
Claudius
  • 550
  • 3
  • 14
6
votes
1 answer

How do I get a variant from a pointer in Delphi?

I need to be able to convert a naked pointer to a variant. I know that the pointer points to a variant, but I can't seem to get it back out. A straight cast (as I pretty much thought) fails: Result := Variant(FAddress)^ returns a compiler error: …
Nick Hodges
  • 16,902
  • 11
  • 68
  • 130
6
votes
1 answer

Why does this get_index implementation fail on VS2017?

Barry gave us this gorgeous get_index for variants: template struct tag { }; template struct get_index; template struct get_index> :…
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
6
votes
2 answers

What are the advantages of using std::variant as opposed to traditional polymorphic processing?

Suppose I have a Shape base class and Circle, Line, and Point derived classes. I have two functions. std::variant process(const Shape &s); Shape process(const Shape& s); I can pass in any of my derived classes and return a…
Mutating Algorithm
  • 2,604
  • 2
  • 29
  • 66
6
votes
1 answer

How does std::variant becomes valueless_by_exception in this example?

this is example inspired by example from cppreference struct S { operator int() { throw 42; } }; int main(){ variant v{12.f}; // OK cout << std::boolalpha << v.valueless_by_exception() << "\n"; try{ …
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
6
votes
1 answer

boost variant comparator

I need to compare two variables of type boost::variant and I want to compare the values inside the variant for equality. What would be the best way to implement this? My variant looks like this: typedef boost::variant
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
6
votes
1 answer

Get item by index from boost::variant like it's possible with std::variant

With std::variant I can call std::get<0>(var) to get the value in the variant as it's first type - int. How can I do this with boost::variant? boost::get<> seems to support only getting by type and not by index and I find the…
onqtam
  • 4,356
  • 2
  • 28
  • 50
6
votes
2 answers

Using std::variant in g++

How can I use std::variant in g++? Why isn't there std::variant in std::experimental (though std::optional is)? What version of g++ do I need? I prefer not to use boost and I'd like to use standard library only. Edit: it seems like only g++ 7…
Aleksandr Tukallo
  • 1,299
  • 17
  • 22
6
votes
2 answers

trivially default constructible std::optional and std::variant

Is it permitable to design std::optional (currently std::experimental::optional) in such a way, that for trivially default constructible type T corresponding std::optional< T > is also trivially default constructible? The same question regading…
Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
6
votes
2 answers

Delphi OleVariant to array of string from COM Library

I have Delphi 2006 client application. This client recieves an Olevariant type data from COM server. The function is: procedure OnLimitsChanged(var SymbolsChanged: {??PSafeArray}OleVariant); This function returns an array of string. I can´t read…
EFD
  • 61
  • 1
  • 2
6
votes
1 answer

boost variant busted in 1_54?

I think Boost::variant is busted in 1_54. I am trying to use a std::unique_ptr with as a bounded type in boost variant. According to the 1_54 documentation, variant needs to be copy constructable or Move Constructable.…
luke signh
  • 139
  • 2
  • 13
6
votes
5 answers

Is there a way to have variants in C# besides using the visitor pattern?

There is no direct support for variant types (aka tagged unions, discriminated unions) in C#. However one can go with a visitor pattern that enables discrimination via double-dispatching and guarantees that all cases are addressed at the compile…
Trident D'Gao
  • 18,973
  • 19
  • 95
  • 159
6
votes
2 answers

C++ leak with VARIANT / bstrVal code

A leak checker tells me that I have a memory leak on memory that is allocated in the following code: // Get the value from the object as a variant. VARIANT vVal; VariantInit ( &vVal ); hres = clsObj->Get ( fieldName.c_str(), 0, &vVal, 0, 0 ); if (…
user1964027
  • 61
  • 1
  • 3
6
votes
1 answer

How to pass SAFEARRAY to COM object through IDispatch?

i am trying to call a method of COM object, where one of the documented parameters is an "array of bytes". The actual declartion depends on the per-language documentation you're looking at: in C# language: byte[] TransformFinalBlock( byte[]…
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219