Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D: Template constraint to show whether a given type is comparable

How would I write a template constraint for the following struct

struct Foo (T, U) {
}

to indicate that both T and U must be comparable using <? By that I mean that two Ts can be compared with < and two Us can be compared with < - a T and a U can be incomparable.

like image 768
Koz Ross Avatar asked Nov 24 '25 01:11

Koz Ross


2 Answers

I believe this will do what you ask, though there may be a more concise solution:

struct Foo (T, U) if (is(typeof(T.init < T.init) : bool) 
                   && is(typeof(U.init < U.init) : bool) 
{ }

You can clean it up a bit with a template:

enum bool isSelfComparable(T) = is(typeof(T.init < T.init) : bool);

struct Foo (T, U) if (isSelfComparable!T && isSelfComparable!U) { }
like image 103
rcorre Avatar answered Nov 26 '25 21:11

rcorre


The most concise way that I can think of doing that at the moment is

struct Foo(T, U)
    if(is(typeof(T[0] < T[0])) && is(typeof(U[0] < U[0])))
{
}

but I'd probably declare it as

struct Foo(T, U)
    if(is(typeof(T.init < T.init)) && is(typeof(U.init < U.init)))
{
}

because it's more straightforward. Some folks might use the use of static arrays confusing, and it's not necessary. But it is technically a bit shorter.

The : bool portion in murphyslaw's answer isn't actually necessary, because < can't result in anything but bool, because the compiler translates <, <=, >, and >= to calls to opCmp on user-defined types, so the programmer doesn't have the opportunity to make them result in anything other than bool (and of course, the comparison operators result in bool for the built-in types). But murphyslaw's answer will work just as well. It's just more verbose than required.

The main place that : bool or == bool would be required would be if you wanted to accept a predicate rather than use the comparison operators directly (since then, you're dealing with an arbitrary function), and that's typically what the generic algorithms in Phobos end up doing. e.g. the signature of one of find's overloads is

InputRange find(alias pred = "a == b", InputRange, Element)
               (InputRange haystack, Element needle)
    if (isInputRange!InputRange &&
        is (typeof(binaryFun!pred(haystack.front, needle)) : bool))
{...}

But if you're planning on using the comparison operators directly, then simply checking that they compile is enough.

like image 22
Jonathan M Davis Avatar answered Nov 26 '25 20:11

Jonathan M Davis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!