Предположим, у нас есть тип X
, значения которого мы хотим сравнить.Предположим далее, что существует не одно сравнение, а семейство сравнений, параметризованное значением другого типа T
.Другими словами, давайте предположим, что нам дана функция прототипа:
bool f(T p, X v1, X v2);
Учитывая параметр p
, f(p, v1, v2)
должно быть истинным, если v1
сравнивает меньше чем v2
в порядкесоответствующий p
.
Теперь я ищу способ перегрузить оператор <
в лексической области видимости, учитывая значение p
типа T
, такое что v1 < v2
в этой области локально скомпилирован в f(p, v1, v2)
.
Просто для иллюстрации следующее достигает того, чего я хочу в Схеме, где ...
обозначает рассматриваемую лексическую область:
(let ((< (lambda (v1 v2) (f p v1 v2))))
...)
У меня есть две идеи о том, как получить почти то, что я хочу в C ++, но я не удовлетворен ими.
Первая идея состоит не в том, чтобы определить оператор сравнения между значениями типа X
, а междузначения типа std::pair <T, X>
.Вместо v1 < v2
нужно написать std::pair (p, v1) < std::pair (p, v2)
, а std::pair (p1, v2) < std::pair (p2, v2)
перегружен для компиляции в f(p1, v1, v2)
.Проблема этого подхода заключается, например, в том, что второй параметр p2
совершенно лишний.Отказ от этого нарушает симметрию.
Моя вторая идея - использовать что-то вроде шаблонов выражений.Здесь v1 < v2
не возвращает логическое значение, а просто абстрактное выражение (дерево), которое оценивается следующим образом: p (v1 < v2)
, где p ()
соответственно перегружено.Проблема этого подхода заключается в том, что нельзя перегружать bool (v1 < v2)
, в частности, такие выражения, как v1 < v2 ? ... : ...
, не будут компилироваться.