我正在构建一个稍微不对称的类。在投诉出现之前,它必然是不对称的。当两个对象一起添加时,必须发生转换(需要花费一些时间的操作),并且转换最自然地发生在正确的加数上。
为了使这个具体,这是一个正在发生的事情的通用例子......
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
,因此必须选择要转换的内容。根据{{1}}的详细信息,最自然地更改左加数以匹配正确的加数。
然而,在做的时候:
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 +
的关联性以实现这一目标?
答案 0 :(得分:3)
你可以做一个黑客攻击。您必须使用其他类型来保存操作的中间结果,然后您可以使用隐式转换来评估结果。以下是如何在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;
}
但是,在这种情况下,我会迅速抛弃+
运算符。我会避免将+
用于任何非关联和可交换的操作,因为这是数学中+
的约定。相反,您可以使用可变参数函数(使用模板)来执行所需的计算。
答案 1 :(得分:3)
有点,但你不会喜欢&#34;怎么&#34;它的。
首先,您需要阅读并理解Boost.Proto文档。然后,您需要弄清楚如何转换所有表达式树以反转操作的顺序。然后,您需要对最终用户透明地表达树的评估。可能在转让?我对Proto没有多少讨论,但与this article on Proto-based optimizations类似的东西可能是一个有用的起点。
答案 2 :(得分:2)
没有。那么为什么不改变右手操作数的优惠呢?
答案 3 :(得分:2)
来自c ++标准第5条,
重载运算符遵循第5章中指定的语法规则。
Where子句5指定运算符优先级和关联性。