- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我在阅读 refuting the notion 之后的第 13.5 节内置运算符不参与重载决议,并注意到没有关于 operator->*
的部分。它只是一个通用的二元运算符。
它的兄弟operator->
、operator*
和operator[]
都要求是非静态成员函数。这排除了将自由函数重载定义为运算符通常用于从对象获取引用。但是不常见的 operator->*
被省略了。
尤其是 operator[]
有很多相似之处。它是二进制的(他们错过了使其成为 n 元的黄金机会),它在左侧接受某种容器,在右侧接受某种定位器。它的特殊规则部分 13.5.5 似乎没有任何实际效果,除了取缔自由函数。 (而且这种限制甚至排除了对交换性的支持!)
例如,这是perfectly legal :
#include <utility>
#include <iostream>
using namespace std;
template< class T >
T &
operator->*( pair<T,T> &l, bool r )
{ return r? l.second : l.first; }
template< class T >
T & operator->*( bool l, pair<T,T> &r ) { return r->*l; }
int main() {
pair<int, int> y( 5, 6 );
y->*(0) = 7;
y->*0->*y = 8; // evaluates to 7->*y = y.second
cerr << y.first << " " << y.second << endl;
}
很容易找到用途,但替代语法往往没那么糟糕。例如,vector
的缩放索引:
v->*matrix_width[2][5] = x; // ->* not hopelessly out of place
my_indexer<2> m( v, dim ); // my_indexer being the type of (v->*width)
m[2][5] = x; // it is probably more practical to slice just once
标准委员会是否忘记防止这种情况发生,是否认为它太丑而无法打扰,或者是否存在实际用例?
最佳答案
我知道的最好的例子是Boost.Phoenix ,这会重载此运算符以实现惰性成员访问。
对于不熟悉 Phoenix 的人来说,它是一个非常漂亮的库,用于构建看起来像普通表达式的 Actor (或函数对象):
( arg1 % 2 == 1 ) // this expression evaluates to an actor
(3); // returns true since 3 % 2 == 1
// these actors can also be passed to standard algorithms:
std::find_if(c.begin(), c.end(), arg1 % 2 == 1);
// returns iterator to the first odd element of c
它通过重载 operator%
和 operator==
实现上述目的。 - 应用于actor arg1
这些操作符返回另一个actor。可以用这种方式构建的表达式范围非常大:
// print each element in c, noting its value relative to 5:
std::for_each(c.begin(), c.end(),
if_(arg1 > 5)
[
cout << arg1 << " > 5\n"
]
.else_
[
if_(arg1 == 5)
[
cout << arg1 << " == 5\n"
]
.else_
[
cout << arg1 << " < 5\n"
]
]
);
在您使用 Phoenix 一段时间后(不是说您会返回),您将尝试以下操作:
typedef std::vector<MyObj> container;
container c;
//...
container::iterator inv = std::find_if(c.begin(), c.end(), arg1.ValidStateBit);
std::cout << "A MyObj was invalid: " << inv->Id() << std::endl;
这会失败,因为 Phoenix 的 Actor 当然没有成员 ValidStateBit
。 Phoenix 通过重载 operator->*
来解决这个问题:
(arg1 ->* &MyObj::ValidStateBit) // evaluates to an actor
(validMyObj); // returns true
// used in your algorithm:
container::iterator inv = std::find_if(c.begin(), c.end(),
(arg1 ->* &MyObj::ValidStateBit) );
operator->*
的参数是:
MyObj *
它返回一个评估 LHS 并在其中查找指定成员的参与者。 (注意:你真的,真的想确保 arg1
返回 MyObj *
- 在你得到一些东西之前你没有看到大量的模板错误Phoenix 出错了。这个小程序产生了 76,738 个痛苦字符(Boost 1.54,gcc 4.6):
#include <boost/phoenix.hpp>
using boost::phoenix::placeholders::arg1;
struct C { int m; };
struct D { int n; };
int main() {
( arg1 ->* &D::n ) (new C);
return 0;
}
关于c++ - 自由 operator->* 重载是邪恶的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2696864/
对于线程和计时器之类的东西,我无法忍受拖放控件。这些控件只是感觉与它们存在的实际本质相去甚远。拖放一个线程?我希望拖拽者在他们这样做之前了解幕后发生的事情。 这些抽象是否离金属太远了?他们是在帮助还是
有些人似乎认为 C 的 strcpy() 函数不好或邪恶。虽然我承认通常最好使用 strncpy() 来避免缓冲区溢出,但以下(strdup() 函数的实现对于那些不幸的人来说拥有它)安全地使用 st
我一直在用 matrix = *((fxMatrix*)&d3dMatrix); 好久不见。它工作正常,直到我的屏幕变黑并在我的办公 table 上收到一桶挫败感。 fxMatrix 包含 4 个 f
这是我应该问的问题,而不是这个: Emacs evil: space as a prefix key in motion state 我想定义一堆用于移动、移动、打开和关闭窗口和缓冲区的命令,这些命令
作为 Vim 用户,我在将近二十年后尝试 Emacs+Evil。我正在将我的大部分 Vim 配置移至 Evil,但我遇到很多问题的一件事是像我在 Vim 中使用的那样设置搜索和突出显示。我想要得到的是
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 9年前关闭
我是一名优秀的程序员,十分优秀!