Why is mostNegative!T not of type T?
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sun Oct 17 19:32:16 UTC 2021
https://github.com/dlang/phobos/blob/master/std/traits.d#L8217
template mostNegative(T)
if (isNumeric!T || isSomeChar!T || isBoolean!T)
{
static if (is(typeof(T.min_normal)))
enum mostNegative = -T.max;
else static if (T.min == 0)
enum byte mostNegative = 0;
else
enum mostNegative = T.min;
}
This is a breakage of the Rule of Least Astonishment: mostNegative!T for
all unsigned types yields type byte.
I tried to simplify as follows:
template mostNegative(T)
if (isNumeric!T || isSomeChar!T || isBoolean!T)
{
static if (is(typeof(T.min_normal)))
enum mostNegative = -T.max;
else
enum mostNegative = T.min;
}
Got errors all the way over in unittests of
std.algorithm.comparison.clamp. Looking at the definition of clamp:
auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
if (is(typeof(max(min(val, upper), lower))))
in
{
import std.functional : greaterThan;
assert(!lower.greaterThan(upper), "Lower can't be greater than
upper.");
}
do
{
return max(min(val, upper), lower);
}
In turn, min and max use mostNegative and makes surprising deductions
based on its type. The surprise has been deemed desirable and has become
part of an unnecessarily complex mesh.
The failing unittest is:
int a = -5;
uint f = 5;
short b = 6;
static assert(is(typeof(clamp(f, a, b)) == int));
This is bizarre and very arguably a bug, as one would expect clamping a
value of type `whatever` would yield a value of type `whatever`.
More information about the Digitalmars-d
mailing list