Printing shortest decimal form of floating point number with Mir

jmh530 john.michael.hall at gmail.com
Wed Dec 23 20:56:26 UTC 2020


On Wednesday, 23 December 2020 at 16:25:58 UTC, 9il wrote:
> [snip]
> 1.
> Alias template function parameter resolution
> https://github.com/dlang/dmd/pull/9778
>
> [snip]

I gave some thought to potential alternatives, but this is really 
the simplest way to think about it.

For instance, I would imagine that something like below would be 
expected to compile if this is ever resolved.

struct Foo(T) {}
alias Bar(T) = Foo!T;
void f(T)(Foo!T x) {}
void b(T)(Bar!T x) {}
void main() {
     auto foo = Foo!int();
     auto bar = Bar!int();
     foo.f;
     foo.b;
     bar.f;
     bar.b;
}

If you instead use template constraints, then you have to rely on 
helper functions for anything more complicated and you are no 
longer following DRY. For instance, a function like
enum bool isBar(T) = is(T == Foo!U, U);
void fb(T)(T x) if(isBar!T) {}
will compile (adjusting the calls above), but you are repeating 
Foo!U.
Because of the bugs mentioned in other posts, replacing isBar 
with below will not.
enum bool isBar(T) = is(T == Bar!U, U);

Given the similarities between template constraints and concepts, 
something like below could accomplish something similar
concept Bar(T) = is(T == Foo!U, U);
but that doesn't help you if you want to also be able to use the 
template alias, as in
auto bar = Bar!int();
This is because Bar(T) in the concept should be passing a Foo!T. 
You would still need to have the alias for Bar if you want that 
functionality (and how to name them when they are doing similar 
things). Abusing C++'s syntax you might have something like
concept Bar(T) = requires(U)() {
     Foo!U; //akin to something like typename T::Foo<U>;
}
where we would basically be telling the compiler that T has to be 
a Foo!U, which would mean you would have to use Bar like 
Bar!U...at least that's the idea. I don't think anything like 
this would work currently in C++.

It's useful to contrast this with implicit conversion. For 
instance, if instead Bar is something like
struct Baz(T)
{
     Foo!T payload
     alias payload this;
}
but then you can no longer have foo get passed to the b function 
(suitably adjusted). So implicit conversion isn't the solution. 
However, it is interesting. The problem is that Baz is a separate 
type. Even if it's implicitly convertible to Foo, a Foo isn't 
convertible to it (every Baz is a Foo but no Foos are Baz's). By 
contrast, the template alias Bar is still a Foo (every Bar is a 
Foo and some but not all Foos are Bars). So it can be thought of 
as a constrained version of Foo, though in this case there are no 
constraints listed. That's where the similarity with C++ concepts 
come in.



More information about the Digitalmars-d-announce mailing list