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