A late reply.
Andrei Alexandrescu:
Typedef!T is meant as a type with the same behavior as T, but
otherwise unrelated to it.<
Right.
Allowing uncontrolled conversions to and fro is only making
typedef weaker.<
Right, on the other hand if this type separation is handled too
much strictly, the code become less handy. So probably some
intermediate point is better, some conversions in controlled
situations.
We could add a flag such that Typedef!(T, supertype) that allows
T as a supertype, i.e. add an alias this.<
That in this program allows the assignments of x1 to x2 and of x2
to x1; but what is this useful for? I think this was discussed a
bit in past:
//-----------
import std.typecons: Proxy;
template Typedef(T) {
alias .Typedef!(T, T.init) Typedef;
}
struct Typedef(T, T init, string cookie=null) {
private T Typedef_payload = init;
this(T init) {
Typedef_payload = init;
}
mixin Proxy!Typedef_payload;
alias Typedef_payload this; // added
}
void main() {
alias T = Typedef!int;
T x1;
int x2;
x1 = x2;
x2 = x1;
}
//-----------
There is no possibility to add implicit construction of
Typedef!T from T (and that's arguably a good thing).<
This is not very handy:
void main() {
import std.typecons: Typedef;
alias T = Typedef!int;
T[] a1 = [1, 2, 3]; // Error
T[T] aa = [1:2, 3:4]; // Error
import std.bigint: BigInt;
BigInt[] a3 = [1, 2, 3]; // Error
}
Some workarounds:
void main() {
import std.typecons: Typedef;
import std.bigint: BigInt;
import std.conv: to;
alias T = Typedef!int;
T[] a1 = [1, 2, 3].to!(T[]); // OK
BigInt[] a2 = [1, 2, 3].to!(BigInt[]); // OK
auto aa1 = [1:2, 3:4].to!(T[BigInt]); // OK
auto aa2 = [1:2, 3:4].to!(BigInt[T]); // OK
}
But it doesn't always work:
import std.typecons: Typedef;
import std.conv: to;
alias T = Typedef!ubyte;
void main() {
T[] a1 = [100.T, 200.T]; // OK
T[] a2 = [100, 200].to!(T[]); // Error
}
Bye,
bearophile