Movatterモバイル変換


[0]ホーム

URL:


D Logo
Menu
Search

Library Reference

version 2.112.0

overview

Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.Requires a signed-in GitHub account. This works well for small changes.If you'd like to make larger changes you may want to consider usinga local clone.

std.variant

This module implements adiscriminated uniontype (a.k.a.tagged union,algebraic type).Such types are usefulfor type-uniform binary interfaces, interfacing with scriptinglanguages, and comfortable exploratory programming.
AVariant object can hold a value of any type, with very fewrestrictions (such asshared types and noncopyable types). Setting the valueis as immediate as assigning to theVariant object. To read back the value ofthe appropriate typeT, use theget method. To query whether aVariant currently holds a value of typeT, usepeek. To fetch theexact type currently held, calltype, which returns theTypeInfo ofthe current value.
In addition toVariant, this module also defines theAlgebraictype constructor. UnlikeVariant,Algebraic only allows a finite set oftypes, which are specified in the instantiation (e.g.Algebraic!(int,string) may only hold anint or astring).
Warning:Algebraic is outdated and not recommended for use in newcode. Instead, usestd.sumtype.SumType.

CreditsReviewed by Brad Roberts. Daniel Keep provided a detailed code reviewprompting the following improvements: (1) better support for arrays; (2) supportfor associative arrays; (3) friendlier behavior towards the garbage collector.

License:
Boost License 1.0.
Authors:
Andrei Alexandrescu

Sourcestd/variant.d

Examples:
Variant a;// Must assign before use, otherwise exception ensues// Initialize with an integer; make the type intVariant b = 42;writeln(b.type);// typeid (int)// Peek at the valueassert(b.peek!(int) !isnull && *b.peek!(int) == 42);// Automatically convert per language rulesauto x = b.get!(real);// Assign any other type, including other variantsa = b;a = 3.14;writeln(a.type);// typeid (double)// Implicit conversions work just as with built-in typesassert(a < b);// Check for convertibilityassert(!a.convertsTo!(int));// double not convertible to int// Strings and all other arrays are supporteda ="now I'm a string";writeln(a);// "now I'm a string"// can also assign arraysa =newint[42];writeln(a.length);// 42a[5] = 7;writeln(a[5]);// 7// Can also assign class valuesclass Foo {}auto foo =new Foo;a = foo;assert(*a.peek!(Foo) == foo);// and full type information is preserved
enum automaxSize(Ts...);
Gives thesizeof the largest type given.
See Also:
Examples:
struct Cat {int a, b, c; }align(1)struct S{long l;ubyte b;}align(1)struct T{ubyte b;long l;}staticassert(maxSize!(int,long) == 8);staticassert(maxSize!(bool,byte) == 1);staticassert(maxSize!(bool, Cat) == 12);staticassert(maxSize!(char) == 1);staticassert(maxSize!(char,short,ubyte) == 2);staticassert(maxSize!(char,long,ubyte) == 8);import std.algorithm.comparison : max;staticassert(maxSize!(long, S) == max(long.sizeof, S.sizeof));staticassert(maxSize!(S, T) == max(S.sizeof, T.sizeof));staticassert(maxSize!(int,ubyte[7]) == 7);staticassert(maxSize!(int,ubyte[3]) == 4);staticassert(maxSize!(int,int,ubyte[3]) == 4);staticassert(maxSize!(void,int,ubyte[3]) == 4);staticassert(maxSize!(void) == 1);
structVariantN(size_t maxDataSize, AllowedTypesParam...);
Back-end type seldom used directly by user code. Two commonly-used types usingVariantN are:
  1. Algebraic: A closed discriminated union with a limited type universe (e.g.,Algebraic!(int, double, string) only accepts these three types and rejects anything else).
  2. Variant: An open discriminated union allowing an unbounded set of types. If any of the types in theVariant are larger than the largest built-in type, they will automatically be boxed. This means that even large types will only be the size of a pointer within theVariant, but this also implies some overhead.Variant can accommodate all primitive types and all user-defined types.
BothAlgebraic andVariant share VariantN's interface. (See their respective documentations below.)
VariantN is a discriminated union type parameterized with the largest size of the types stored (maxDataSize) and with the list of allowed types (AllowedTypes). If the list is empty, then any type up of size up to maxDataSize (rounded up for alignment) can be stored in aVariantN object without being boxed (types larger than this will be boxed).
Examples:
alias Var =VariantN!(maxSize!(int,double, string));Var a;// Must assign before use, otherwise exception ensues// Initialize with an integer; make the type intVar b = 42;writeln(b.type);// typeid (int)// Peek at the valueassert(b.peek!(int) !isnull && *b.peek!(int) == 42);// Automatically convert per language rulesauto x = b.get!(real);// Assign any other type, including other variantsa = b;a = 3.14;writeln(a.type);// typeid (double)// Implicit conversions work just as with built-in typesassert(a < b);// Check for convertibilityassert(!a.convertsTo!(int));// double not convertible to int// Strings and all other arrays are supporteda ="now I'm a string";writeln(a);// "now I'm a string"
Examples:
can also assign arrays
alias Var =VariantN!(maxSize!(int[]));Var a =newint[42];writeln(a.length);// 42a[5] = 7;writeln(a[5]);// 7
Examples:
Can also assign class values
alias Var =VariantN!(maxSize!(int*));// classes are pointersVar a;class Foo {}auto foo =new Foo;a = foo;assert(*a.peek!(Foo) == foo);// and full type information is preserved
aliasAllowedTypes = This2Variant!(VariantN, AllowedTypesParam);
The list of allowed types. If empty, any type is allowed.
enum boolallowed(T);
Tells whether a typeT is statically allowed for storage inside aVariantN object by lookingT up inAllowedTypes.
this(T)(Tvalue);
Constructs aVariantN value given an argument of a generic type. Statically rejects disallowed types.
this(T : VariantN!(tsize, Types), size_t tsize, Types...)(Tvalue)
if (!is(T : VariantN) && (Types.length > 0) && allSatisfy!(allowed, Types));
Allows assignment from a subset algebraic type
VariantNopAssign(T)(Trhs);
Assigns aVariantN from a generic argument. Statically rejects disallowed types.
pure nothrow @property boolhasValue() const;
Returns true if and only if theVariantN object holds a valid value (has been initialized with, or assigned from, a valid value).
Examples:
Variant a;assert(!a.hasValue);Variant b;a = b;assert(!a.hasValue);// still no valuea = 5;assert(a.hasValue);
@property inout(T)*peek(T)() inout;
If theVariantN object holds a value of theexact typeT, returns a pointer to that value. Otherwise, returnsnull. In cases whereT is statically disallowed, peek will not compile.
Examples:
Variant a = 5;auto b = a.peek!(int);assert(b !isnull);*b = 6;writeln(a);// 6
nothrow @property @trusted TypeInfotype() const;
Returns thetypeid of the currently held value.
@property boolconvertsTo(T)() const;
Returnstrue if and only if theVariantN object holds an object implicitly convertible to typeT. Implicit convertibility is defined as perAllImplicitConversionTargets.
@property inout(T)get(T)() inout;

@property autoget(uint index)() inout
if (index < AllowedTypes.length);
Returns the value stored in theVariantN object, either by specifying the needed type or the index in the list of allowed types. The latter overload only applies to bounded variants (e.g.Algebraic).
Parameters:
TThe requested type. The currently stored value must implicitly convert to the requested type, in factDecayStaticToDynamicArray!T. If an implicit conversion is not possible, throws aVariantException.
indexThe index of the type amongAllowedTypesParam, zero-based.
@property Tcoerce(T)();
Returns the value stored in theVariantN object, explicitly converted (coerced) to the requested type T. IfT is a string type, the value is formatted as a string. If theVariantN object is a string, a parse of the string to typeT is attempted. If a conversion is not possible, throws a VariantException.
stringtoString();
Formats the stored value as a string.
boolopEquals(T)(auto ref Trhs) const
if (allowed!T || is(immutable(T) == immutable(VariantN)));
Comparison for equality used by the "==" and "!=" operators.
intopCmp(T)(Trhs)
if (allowed!T);
Ordering comparison used by the "<", "<=", ">", and ">=" operators. In case comparison is not sensible between the held value andrhs, an exception is thrown.
nothrow @safe size_ttoHash() const;
Computes the hash of the held value.
VariantNopBinary(string op, T)(Trhs)
if ((op == "+" || op == "-" || op == "*" || op == "/" || op == "^^" || op == "%") && is(typeof(opArithmetic!(T, op)(rhs))));

VariantNopBinary(string op, T)(Trhs)
if ((op == "&" || op == "|" || op == "^" || op == ">>" || op == "<<" || op == ">>>") && is(typeof(opLogic!(T, op)(rhs))));

VariantNopBinaryRight(string op, T)(Tlhs)
if ((op == "+" || op == "*") && is(typeof(opArithmetic!(T, op)(lhs))));

VariantNopBinaryRight(string op, T)(Tlhs)
if ((op == "&" || op == "|" || op == "^") && is(typeof(opLogic!(T, op)(lhs))));

VariantNopBinary(string op, T)(Trhs)
if (op == "~");

VariantNopOpAssign(string op, T)(Trhs);
Arithmetic betweenVariantN objects and numeric values. All arithmetic operations return aVariantN object typed depending on the types of both values involved. The conversion rules mimic D's built-in rules for arithmetic conversions.
inout(Variant)opIndex(K)(Ki) inout;

VariantopIndexAssign(T, N)(Tvalue, Ni);

VariantopIndexOpAssign(string op, T, N)(Tvalue, Ni);
Array and associative array operations. If a VariantN contains an (associative) array, it can be indexed into. Otherwise, an exception is thrown.
Examples:
Variant a =newint[10];a[5] = 42;writeln(a[5]);// 42a[5] += 8;writeln(a[5]);// 50int[int] hash = [ 42:24 ];a = hash;writeln(a[42]);// 24a[42] /= 2;writeln(a[42]);// 12
@property size_tlength();
If theVariantN contains an (associative) array, returns the length of that array. Otherwise, throws an exception.
intopApply(Delegate)(scope Delegatedg)
if (is(Delegate == delegate));
If theVariantN contains an array, appliesdg to each element of the array in turn. Otherwise, throws an exception.
templateAlgebraic(T...)
Algebraic data type restricted to a closed set of possibletypes. It's an alias forVariantN with anappropriately-constructed maximum size.Algebraic isuseful when it is desirable to restrict what a discriminated typecould hold to the end of defining simpler and more efficientmanipulation.
Warning:Algebraic is outdated and not recommended for use in newcode. Instead, usestd.sumtype.SumType.
Examples:
auto v =Algebraic!(int,double, string)(5);assert(v.peek!(int));v = 3.14;assert(v.peek!(double));// auto x = v.peek!(long); // won't compile, type long not allowed// v = '1'; // won't compile, type char not allowed
Examples:

Self-Referential Types

A useful and popular use of algebraic data structures is for definingself-referential data structures, i.e. structures that embed references tovalues of their own type within.
This is achieved withAlgebraic by usingThis as a placeholder whenever areference to the type being defined is needed. TheAlgebraic instantiationwill performalpha renaming on its constituent types, replacingThiswith the self-referenced type. The structure of the type involvingThis maybe arbitrarily complex.
import std.typecons : Tuple, tuple;// A tree is either a leaf or a branch of two other treesalias Tree(Leaf) =Algebraic!(Leaf, Tuple!(This*, This*));Tree!int tree = tuple(new Tree!int(42),new Tree!int(43));Tree!int* right = tree.get!1[1];writeln(*right);// 43// An object is a double, a string, or a hash of objectsalias Obj =Algebraic!(double, string, This[string]);Obj obj ="hello";writeln(obj.get!1);// "hello"obj = 42.0;writeln(obj.get!0);// 42obj = ["customer": Obj("John"),"paid": Obj(23.95)];writeln(obj.get!2["customer"]);// "John"
aliasVariant = VariantN!32LU.VariantN;
Alias forVariantN instantiated with the largest size ofcreal,char[], andvoid delegate(). This ensures thatVariant is large enoughto hold all of D's predefined types unboxed, including all numeric types,pointers, delegates, and class references. You may want to useVariantN directly with a different maximum size either forstoring larger types unboxed, or for saving memory.
Examples:
Variant a;// Must assign before use, otherwise exception ensues// Initialize with an integer; make the type intVariant b = 42;writeln(b.type);// typeid (int)// Peek at the valueassert(b.peek!(int) !isnull && *b.peek!(int) == 42);// Automatically convert per language rulesauto x = b.get!(real);// Assign any other type, including other variantsa = b;a = 3.14;writeln(a.type);// typeid (double)// Implicit conversions work just as with built-in typesassert(a < b);// Check for convertibilityassert(!a.convertsTo!(int));// double not convertible to int// Strings and all other arrays are supporteda ="now I'm a string";writeln(a);// "now I'm a string"
Examples:
can also assign arrays
Variant a =newint[42];writeln(a.length);// 42a[5] = 7;writeln(a[5]);// 7
Examples:
Can also assign class values
Variant a;class Foo {}auto foo =new Foo;a = foo;assert(*a.peek!(Foo) == foo);// and full type information is preserved
Variant[]variantArray(T...)(Targs);
Returns an array of variants constructed fromargs.
This is by design. During construction theVariant needs static type information about the type being held, so as to store a pointer to function for fast retrieval.
Examples:
auto a =variantArray(1, 3.14,"Hi!");writeln(a[1]);// 3.14auto b = Variant(a);// variant array as variantwriteln(b[1]);// 3.14
classVariantException:object.Exception;
Thrown in three cases:
  1. An uninitializedVariant is used in any way except assignment andhasValue;
  2. Aget orcoerce is attempted with an incompatible target type;
  3. A comparison betweenVariant objects of incompatible types is attempted.
Examples:
import std.exception : assertThrown;Variant v;// uninitialized useassertThrown!VariantException(v + 1);assertThrown!VariantException(v.length);// .get with an incompatible target typeassertThrown!VariantException(Variant("a").get!int);// comparison between incompatible typesassertThrown!VariantException(Variant(3) < Variant("a"));
TypeInfosource;
The source type in the conversion or comparison
TypeInfotarget;
The target type in the conversion or comparison
templatevisit(Handlers...) if (Handlers.length > 0)
Applies a delegate or function to the givenAlgebraic depending on the held type, ensuring that all types are handled by the visiting functions.
The delegate or function having the currently held value as parameter is called withvariant's current value. Visiting handlers are passed in the template parameter list. It is statically ensured that all held types ofvariant are handled across all handlers.visit allows delegates and static functions to be passed as parameters.
If a function with an untyped parameter is specified, this function is called when the variant contains a type that does not match any other function. This can be used to apply the same function across multiple possible types. Exactly one generic function is allowed.
If a function without parameters is specified, this function is called whenvariant doesn't hold a value. Exactly one parameter-less function is allowed.
Duplicate overloads matching the same type in one of the visitors are disallowed.
Returns:
The return type of visit is deduced from the visiting functions and must be the same across all overloads.
Throws:
VariantException ifvariant doesn't hold a value and no parameter-less fallback function is specified.
Examples:
Algebraic!(int, string) variant;variant = 10;assert(variant.visit!((string s) =>cast(int) s.length,                      (int i)    => i)()                      == 10);variant ="string";assert(variant.visit!((int i) => i,                      (string s) =>cast(int) s.length)()                      == 6);// Error function usageAlgebraic!(int, string) emptyVar;auto rslt = emptyVar.visit!((string s) =>cast(int) s.length,                      (int i)    => i,                      () => -1)();writeln(rslt);// -1// Generic function usageAlgebraic!(int,float,real) number = 2;writeln(number.visit!(x => x += 1));// 3// Generic function for int/float with separate behavior for stringAlgebraic!(int,float, string) something = 2;assert(something.visit!((string s) => s.length, x => x) == 2);// genericsomething ="asdf";assert(something.visit!((string s) => s.length, x => x) == 4);// string// Generic handler and empty handlerAlgebraic!(int,float,real) empty2;writeln(empty2.visit!(x => x + 1, () => -1));// -1
autovisit(VariantType)(VariantTypevariant)
if (isAlgebraic!VariantType);
templatetryVisit(Handlers...) if (Handlers.length > 0)
Behaves asvisit but doesn't enforce that all types are handled by the visiting functions.
If a parameter-less function is specified it is called when eithervariant doesn't hold a value or holds a type which isn't handled by the visiting functions.
Returns:
The return type of tryVisit is deduced from the visiting functions and must be the same across all overloads.
Throws:
VariantException ifvariant doesn't hold a value orvariant holds a value which isn't handled by the visiting functions, when no parameter-less fallback function is specified.
Examples:
Algebraic!(int, string) variant;variant = 10;auto which = -1;variant.tryVisit!((int i) { which = 0; })();writeln(which);// 0// Error function usagevariant ="test";variant.tryVisit!((int i) { which = 0; },                  ()      { which = -100; })();writeln(which);// -100
autotryVisit(VariantType)(VariantTypevariant)
if (isAlgebraic!VariantType);
Copyright © 1999-2026 by theD Language Foundation | Page generated byDdoc on Fri Feb 20 00:53:36 2026

[8]ページ先頭

©2009-2026 Movatter.jp