使用 Boost.Phoenix 的运算符 ->*
Using Boost.Phoenix's operator ->*
我正在玩Phoenix v3,试图弄清楚我们是否应该标准化它,而不是当前的Bind和Lambda的混合。从文档中我得到的印象是,应该有可能简化一些表达式。
目前我坚持使用->*操作符与STL算法相结合。下面的代码可以编译(Visual Studio 2008 SP1),但没有给出预期的输出:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/mem_fn.hpp>
#include <boost/phoenix.hpp>
using namespace std;
using namespace boost;
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
struct A
{
void f() const { cout << "A"; };
};
struct B
{
A a() { return A(); };
};
int main()
{
vector<A> va(1);
for_each(va.begin(), va.end(), bind(mem_fn(&A::f), arg1));
for_each(va.begin(), va.end(), arg1->*&A::f);
vector<B> vb(1);
for_each(vb.begin(), vb.end(), bind(mem_fn(&A::f), bind(mem_fn(&B::a), arg1)));
return 0;
}
运行这个例子将输出'A'两次,两次都是基于绑定的循环。下面是我的问题:
- 为了让基于操作符的循环实际上调用A::f,我应该做些什么改变?
- 如何使用操作符更改双绑定循环? 谁知道为什么VS2008总是抱怨当你不指定mem_fn在这些情况下?我总是得到警告C4180(限定符应用于函数类型没有意义;忽视)。
提前感谢你的真知灼见
给定:
#include <algorithm>
#include <vector>
#include <iostream>
#include <boost/phoenix.hpp>
struct A
{
void f() const { std::cout << "An"; };
};
struct B
{
A a() const { return A(); };
};
第一个很容易修复:
int main()
{
using boost::phoenix::arg_names::arg1;
std::vector<A> va(1);
std::for_each(va.begin(), va.end(), (&arg1->*&A::f)());
}
关于operator->*
, Phoenix文档明确指出:
成员指针操作符的左侧必须是返回指针类型的参与者。
因此,当给定一个对象(在本例中是A&
)时,必须获取该对象的地址才能使用operator->*
——因此是&arg1
。(另外,由于Phoenix actor是惰性的,因此必须使用额外的圆括号来获得急切函子,而不是惰性函子。)
第二个操作就不那么简单了,因为不能只使用操作符——因为我们必须有一个actor来表示指针才能使用operator->*
,我们需要获取B::a
结果的地址,但是B::a
的结果是右值,获取任何右值的地址都是非法的。我们有两个选项:
将
来完成B::a
的结果存储到一个变量中,使其为左值,从而使获取的地址合法。这可以使用phoenix::let
:int main() { using boost::phoenix::let; using boost::phoenix::arg_names::arg1; using boost::phoenix::local_names::_a; std::vector<B> vb(1); std::for_each( vb.begin(), vb.end(), (let(_a = (&arg1->*&B::a)())[(&_a->*&A::f)()]) ); }
使用
phoenix::bind
代替operator->*
,因为它对引用和指针同样有效,避免了需要获取B::a
结果的地址:int main() { using boost::phoenix::bind; using boost::phoenix::arg_names::arg1; std::vector<B> vb(1); std::for_each(vb.begin(), vb.end(), bind(&A::f, (&arg1->*&B::a)())); }
我也不太擅长phoenix,但是我认为你不能按照你想要的方式使用->*运算符。
如果您将示例更改为
...
vector<A*> va;
va.push_back(new A);
for_each(va.begin(), va.end(), bind(mem_fn(&A::f), arg1));
for_each(va.begin(), va.end(), (arg1->*&A::f)());
...
你将得到两次a。在示例中,我只找到了带有指针的示例,所以我猜你只能对指针使用凤凰->*操作符。这应该没问题,因为操作符->*绑定了指针。
摘自5.5中的规范:
二进制操作符->*绑定第二个操作数,该操作数必须为of类型"指向T成员的指针"(其中T是一个完全定义的类)类型)到它的第一个操作数,该操作数的类型应为"指向T的指针"或指向一个类的指针,其中T是一个明确的、可访问的基类类
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 增量运算符与后缀混淆
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 模板类无法识别友元运算符
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 关闭||运算符优化
- 通过继承类使用来自不同命名空间的运算符
- C++Cast运算符过载
- 如何使用AngelScript注册SFML Vector2运算符
- 重载元组索引运算符-C++
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 布尔比较运算符是如何在C++中工作的
- 重载运算符new[]的行为取决于析构函数
- 是否需要使用 - &gt;运算符在C 中调用成员函数时