D: Ограничение шаблона, чтобы показать, сопоставим ли данный тип

Как бы я написал ограничение шаблона для следующей структуры

struct Foo (T, U) {
}

чтобы указать, что и T, и U должны быть сопоставимы, используя <? Под этим я подразумеваю, что два T можно сравнить с <, а два U можно сравнить с <, а T и U могут быть несравнимы.


person Koz Ross    schedule 03.12.2014    source источник


Ответы (2)


Я считаю, что это сделает то, что вы просите, хотя может быть более краткое решение:

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

Вы можете немного почистить его с помощью шаблона:

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

struct Foo (T, U) if (isSelfComparable!T && isSelfComparable!U) { }
person rcorre    schedule 03.12.2014

Самый краткий способ, который я могу придумать, это сделать на данный момент

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

но я бы, вероятно, объявил это как

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

потому что это более прямолинейно. Некоторых людей может сбить с толку использование статических массивов, и это не обязательно. Но технически он немного короче.

Часть : bool в ответе murphyslaw на самом деле не нужна, потому что < не может привести ни к чему, кроме bool, потому что компилятор преобразует <, <=, > и >= в вызовы opCmp для пользовательских типов, поэтому у программиста нет возможности заставить их давать результат, отличный от bool (и, конечно, операторы сравнения приводят к bool для встроенные типы). Но ответ Мерфислоу будет работать так же хорошо. Это просто более подробно, чем требуется.

Основное место, где : bool или == bool потребуются, было бы, если бы вы хотели принять предикат, а не использовать операторы сравнения напрямую (поскольку вы имеете дело с произвольной функцией), и это обычно то, чем заканчиваются общие алгоритмы в Phobos делать. например подпись одной из перегрузок find

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

Но если вы планируете использовать операторы сравнения напрямую, достаточно просто проверить, что они компилируются.

person Jonathan M Davis    schedule 06.12.2014