簡體   English   中英

用戶定義的中綴運算符

[英]User-defined infix operators

在C ++中引入新的中綴運算符很容易

// User-defined infix operator framework

template <typename LeftOperand, typename Operation>
struct LeftHelper
{
    const LeftOperand& leftOperand;
    const Operation& operation;
    LeftHelper(const LeftOperand& leftOperand, 
               const Operation& operation)
        : leftOperand(leftOperand), operation(operation) {}
};

template <typename LeftOperand, typename Operation >
auto operator < (const LeftOperand& leftOperand, 
                 Operation& operation)
{
    return LeftHelper<LeftOperand, Operation>(leftOperand, operation);
}

template <typename LeftOperand, typename Operation, typename RightOperand>
auto operator > (LeftHelper<LeftOperand, Operation> leftHelper, 
                 const RightOperand& rightOperand)
{
    return leftHelper.operation(leftHelper.leftOperand, rightOperand);
}

// Defining a new operator

#include <cmath>
static auto pwr = [](const auto& operand1, const auto& operand2) { return std::pow(operand1, operand2); };

// using it
#include <iostream>
int main() 
{
   std::cout << (2 <pwr> 16) << std::endl;
   return 0;
}

現場演示

不幸的是,這個冪運算符具有錯誤的優先級和相關性。 所以我的問題是: 如何解決這個問題? 我希望我的<pow>具有比*更高的優先級並且與右邊相關聯,就像在數學符號中一樣。

編輯可以通過使用不同的括號來改變優先級,例如|op| /op/*op*或者甚至,如果有人傾向於<<--op-->> ,但是這種方式不能高於最高內置運算符優先級。 但是今天C ++在模板元編程和類型推導方面是如此強大,只需要一些其他方法來實現所需的結果。

另外,如果我可以使用pow而不是pwr ,那將是很好的。 不幸的是,在某些實現中, #include <cmath>pow帶入全局命名空間,因此會發生沖突。 我們可以重載operator not表單的聲明

not using std::pow;

從全局命名空間中刪除了std::pow

進一步閱讀: Bjarne Stroustrup的相關提案

最小驚喜的原則很重要,並且a*b *power* c * d評估為a* (b^c) *d 幸運的是,有一個簡單的解決方案。

要確保*power*具有比乘法更高的優先級,您必須使用類似的命名運算符技術進行乘法。

然后,而不是直接計算*power**times* ,而是構建表達式樹。 評估時,此表達式樹可以應用任意優先級規則

我們可以對每個內置運算符執行此操作,為我們提供易於閱讀的語法,允許運算符優先級的編譯時元編程:

auto z =equals= bracket<
  a *plus* b *times* c *power* bracket<
    a *plus* b
  >bracket *power* x *times* y
>bracket;

為避免此表達式模板的存儲時間超過最佳值,只需重載operator auto()&&即可返回推導出的類型。 如果您的編譯器不支持該功能, =equals=可以以較低的清晰度成本返回正確的類型。

請注意,上述語法實際上可以使用類似於OP的技術在C ++中實現。 實際實現大於SO帖子應包含的內容。

還有其他好處。 眾所周知,編程語言中隱藏的ASCII字符已經失寵,閱讀C ++的人可能會被以下表達式所困擾:

int z = (a + b* pow(c,pow(x,a+b))*y);

使用這種技術,所有運算符都具有可讀的名稱,使其含義清晰,並且所有操作都使用中綴而不是混合中綴和前綴表示法。

類似的解決方案,以確保pow可通過重新實現來完成<cmath><cmath_nopow>自己。 這避免了操作符不會在語言結構上重載,這會導致AST語法monad解耦和/或違反標准。 也許嘗試Haskell?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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