Since we have the pattern of returning float.nan from opCmp to signal incomparable values, it makes sense to have a trait to identify this behavior. Something like this:
template hasNanComparison(T1, T2 = T1)
{
static if (isFloatingPoint!T1)
enum hasNanComparison = true;
else static if (!isAggregateType!T1)
enum hasNanComparison = false;
else static if (!is(typeof((T1 a, T2 b) => a.opCmp(b))))
enum hasNanComparison = false;
else
enum hasNanComparison = hasNanComparison!(ReturnType!((T1 a, T2 b) => a.opCmp(b)));
}
///
@safe unittest
{
assert( hasNanComparison!float);
assert( hasNanComparison!real);
assert(!hasNanComparison!int);
assert(!hasNanComparison!string);
assert(!hasNanComparison!(int*));
assert(!hasNanComparison!(int[]));
struct S
{
float opCmp(S s)
{
return float.nan;
}
}
assert( hasNanComparison!S);
struct S2
{
S opCmp(S2 s)
{
return S();
}
}
assert( hasNanComparison!S2);
}