Why is std.variant bad?

monkyyy crazymonkyyy at gmail.com
Mon Sep 22 22:53:43 UTC 2025


On Saturday, 20 September 2025 at 03:01:55 UTC, Paul Backus wrote:
> On Saturday, 20 September 2025 at 01:46:47 UTC, monkyyy wrote:
>> This was before my time. I was under the impression that it 
>> was somehow class and oo related badness when people talked 
>> about using TypeInfo; but when I my own experiments say that 
>> typeinfo is just another tool
>>
>> I see 3k lines of code compared to my 50; Im going to say its 
>> but the postmorden seems wrong.
>>
>> my code: 
>> https://gist.github.com/crazymonkyyy/14e36a99dd307c5d6e37bdb3ca2524a7
>
> IMO there isn't really anything wrong with `Variant`. Given 
> what it's trying to do, using `TypeInfo` or something similar 
> is pretty much unavoidable. (Technically, `Variant` uses its 
> own custom form of RTTI that's more lightweight than 
> `TypeInfo`, but it still requires an extra level of indirection 
> at runtime.)
>
> The problem is with `Algebraic`, which uses RTTI even when all 
> of the types are known at compile time--totally unnecessary.

thoughts on this direction?

```d
#!opend test app
import std;

struct introspectivepointer(alias F,T){
	void* me;
	T meta;
	void opAssign(T)(ref T t){
		me=cast(void*)&t;
		meta=F(t);
	}
	ref T get(T)(){
		assert(meta==F(*cast(T*)me));
		return *cast(T*)me;
	}
}

unittest{//sumtype-like
	introspectivepointer!(a=>typeid(a),TypeInfo) foo;
	foo=int(3);
	foo.get!int.writeln;//3
	foo=13.37;
	//foo.get!int.writeln;//error [unittest] double != int
}

unittest{//rip and tear
	struct vec2{int x,y;}
	struct circle{
		vec2 pos;
		int r;
	}
	struct rect{
		int w,h;
		vec2 pos;
	}
	introspectivepointer!(a=>a.pos.offsetof,ulong) shape;
	void move(typeof(shape) s){
		(*cast(vec2*)(s.me+s.meta)).y+=5;
	}
	auto foo=circle(vec2(1,1),5);
	auto bar=rect(3,5,vec2(3,3));
	shape=foo;
	move(shape);
	foo.writeln;//circle(vec2(1, 6), 5)
	shape.get!circle.writeln;//circle(vec2(1, 6), 5)
	shape=bar;
	move(shape);
	bar.writeln;//rect(3, 5, vec2(3, 8))
}
bool isNull(float f)=>f.isNaN;
unittest{//verify nullable
	Nullable!int i=15;
	introspectivepointer!(a=>tuple(typeid(a),a.isNull),Tuple!(TypeInfo,bool)) refi;
	refi=i;
	i=30;
	refi.get!(typeof(i)).writeln;//30
	i.nullify;
	//refi.get!(typeof(i)).writeln;//ugly but an error
	float f=13.37;
	refi=f;//!!!!!
	refi.get!float.writeln;//13.37
}
```


More information about the Digitalmars-d-learn mailing list