[英]Is it possible to overload operator associativity in 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;
}
為了添加兩個Foo
,它們需要具有相同的_fav
,因此必須選擇要轉換哪個。 基於Foo
的細節,最自然的是改變左加數以匹配正確的加數。
但是,在做的時候:
Foo A,B,C;
Foo D = A + B + C; // D = (A + B) + C
Foo E = A + (B + C);
如果A
已經具有與C
相同的_fav
,則對D
調用兩次changeFav
(一次將A._fav
更改為B._fav
,然后再將(A+B)._fav
更改為(A+B)._fav
到C._fav
)和一次為E
(將B._fav
改為C._fav
)。 我更喜歡后者,但希望避免強迫用戶使用括號進行多次添加。
有沒有辦法超載operator +
的關聯性來實現這一點?
你可以做一個黑客。 您必須使用其他類型來保存操作的中間結果,然后您可以使用隱式轉換來評估結果。 以下是如何在C ++中實現Python樣式比較運算符的示例:
#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;
}
然而,在這種情況下,我會快速拋棄+
運算符。 我會避免將+
用於任何非關聯和可交換的操作,因為這是數學中+
的約定。 相反,您可以使用可變參數函數(使用模板)來執行所需的計算。
有點,但你不會喜歡它的“如何”。
首先,您需要閱讀並理解Boost.Proto文檔。 然后,您需要弄清楚如何轉換所有表達式樹以反轉操作的順序。 然后,您需要對最終用戶透明地表達樹的評估。 可能在轉讓? 我對Proto沒有多少討論,但是類似於這篇關於基於Proto的優化的文章可能是一個有用的起點。
不,那么為什么不改變右手操作數的優惠呢?
從c ++標准第5條開始,
重載運算符遵循第5章中指定的語法規則。
Where第5節規定了運算符優先級和關聯性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.