Можно ли перегрузить ассоциативность операторов в C ++?

Я строю класс с немного асимметричным дополнением. Прежде чем поступить жалобы, она обязательно должна быть асимметричной. Существует преобразование (операция, которая занимает немного времени), которое должно произойти, когда два объекта добавляются вместе, и преобразование наиболее естественно происходит относительно правильного слагаемого.

Чтобы сделать это конкретным, вот общий пример того, что происходит …

class Foo {
char _fav;
int _prop;

public:
const char fav() const {return _fav;}
const int prop() const (return _prop;}
void changeFav(char); // complicated method that also changes _prop
void changeProp(int); // straightforward method
}

Foo
operator + (Foo A, Foo B) {
Foo sum;
if (A.fav() != B.fav()) A.changeFav(B.fav);
sum.changeProp(A.prop() + B.prop());
return sum;
}

На двоих Foos, которые будут добавлены, они должны иметь одинаковые _favТаким образом, выбор должен быть сделан, чтобы преобразовать. На основании деталей Foo, наиболее естественно изменить левое слагаемое, чтобы оно соответствовало правому слагаемому.

Однако при выполнении:

Foo A,B,C;
Foo D = A + B + C; // D = (A + B) + C
Foo E = A + (B + C);

если A уже имеет то же самое _fav как C, затем changeFav вызывается дважды для D (один раз поменять A._fav в B._fav а потом снова поменять (A+B)._fav в C._fav) и один раз для E (изменить B._fav в C._fav). Я предпочитаю последнее, но хочу избегать принуждения пользователя использовать скобки для многократного добавления.

Есть ли способ перегрузить ассоциативность operator + чтобы это произошло?

3

Решение

Из c ++ стандартного пункта 5,

Перегруженные операторы подчиняются правилам синтаксиса, указанным в разделе 5.

Где пункт 5 определяет приоритет оператора и ассоциативность.

2

Другие решения

Вы можете сделать взломать. Вы должны использовать другой тип для хранения промежуточных результатов операции, затем вы можете использовать неявное приведение для оценки результата. Вот пример того, как реализовать операторы сравнения в стиле Python в C ++:

#include <vector>
#include <cstdio>

struct S {
S(int x) : val(x) { }
int val;
};

struct Comparison {
std::vector<S> operands;
explicit Comparison(S x)
{
operands.push_back(x);
}
operator S()
{
auto i = operands.begin(), e = operands.end();
S prev = *i;
for (i++; i != e; i++) {
S cur = *i;
if (prev.val >= cur.val)
return S(0);
prev = cur;
}
return S(1);
}
void append(const Comparison &a)
{
operands.insert(
operands.end(),
a.operands.begin(),
a.operands.end());
}
void append(const S &a)
{
operands.push_back(a);
}
};

Comparison operator<(const Comparison &left, const Comparison &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const Comparison &left, const S &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const S &left, const Comparison &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const S &left, const S &right)
{ Comparison result(left); result.append(right); return result; }

int main()
{
S x(0);
x = S(0) < S(1) < S(2) < S(3);
std::printf("0 < 1 < 2 < 3 = %d\n", x.val);
x = S(0) < S(1) < S(3) < S(2);
std::printf("0 < 1 < 3 < 2 = %d\n", x.val);
return 0;
}

Однако в такой ситуации я бы быстро бросил + оператор. Я бы не использовал + для любой операции, которая не является ассоциативной и коммутативной, так как это соглашение для + по математике Вместо этого вы можете использовать переменную функцию (используя шаблоны) для выполнения желаемого вычисления.

3

Конечно, но вам не понравится «как».

Прежде всего, вам нужно прочитать и понять Boost.Proto документация. Затем вам нужно выяснить, как преобразовать все деревья выражений, чтобы изменить порядок операций. Затем необходимо сделать оценку деревьев выражений прозрачной для конечного пользователя. Возможно по заданию? Я не слишком много возился с Прото, но что-то похожее на эта статья о Прото-основанных оптимизациях может быть полезным для начала.

3

Нет. Так почему бы не изменить вместо этого предпочтение правого операнда?

2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector