grauzone wrote:
Consider if opImplicitCastFrom was implemented and you had a function "void foo(Variant[] x...)", would it be possible to pass a Variant[] to it, that will be directly used as "x"?

For example:

void foo(Variant[] x...) {
    writefln(x);
}

Variant[] t = [1,2,3];
foo(t);

Yah, in fact this compiles and runs:

import std.variant;
import std.stdio;

void foo(Variant[] x...) {
    writeln(x);
}

void main()
{
    auto t = variantArray(1,2,3);
    foo(t);
}

Possible output 1:
[1, 2, 3]

Possible output 2:
[[1, 2, 3]]

The former is correct.

This is a slight ambiguity. Will "t" be packed into a Variant, or will it directly assign "t" to "x" as if there wasn't an opImplicitCastFrom(T)? Would it be a compilation error?

Anyway. If this would work, chaining function calls would be simple, and wouldn't require additional wrapper functions.

So IMHO:

(a) Variadics with templates are good;

The "void foo(Variant[] dynatyped...)" isn't a template. But if on the caller side you can use it as if it was a "void foo(T)(T...)" or a "void foo(...)", everything is fine.

(b) Variadics with uniform-type arrays are good;

Sure.

(c) We should avoid variadics with void*.

Well, it isn't really important whether you use a (TypeInfo, void*) tuple, or a Variant for passing around data of a dynamic type unknown at compile time. Of course, Variant is much nicer.

I was only suggesting void*, because for classic variadics, it's probably simpler to implement on the compiler side. (Although, as you said, it's hard to convert a (TypeInfo, void*) to Variant.)

The advantage of Variant is a tad subtle. Variant is part of the standard library and as such it's trusted code. Although it internally uses unsafe features, it offers a safe interface. In contrast, void* essentially trusts the application programmer.


Andrei

Reply via email to