簡體   English   中英

是否有可能在C ++中重載運算符關聯性?

[英]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)._favC._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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM