【发布时间】:2012-04-26 18:45:39
【问题描述】:
有人可以推荐 tr1 的 mem_fn 和绑定实用程序的一些很酷的实际用途吗?我不需要深奥的 C++ 来开发库。只是一些利用这些的应用程序级编码。
任何帮助将不胜感激。
【问题讨论】:
有人可以推荐 tr1 的 mem_fn 和绑定实用程序的一些很酷的实际用途吗?我不需要深奥的 C++ 来开发库。只是一些利用这些的应用程序级编码。
任何帮助将不胜感激。
【问题讨论】:
我已将std::mem_fn 和std::bind 用于反射样式属性。
所以我会有一个带有AbstractProperty 向量的class SomeClass。 AbstractProperty可以有几种不同类型的类,比如PropertyFloat、PropertyU32等。
然后在SomeClass 中,我会将bind 发送到std::function 以获取AbstractProperty。我会 bind 这样做
std::bind(std::mem_fn(&SomeClass::SomeFloatGetter), this)
对于 setter 类型的函数,我会使用
std::bind(std::mem_fn(&SomeClass::SomeSetterGetter), this, std::placeholders::_1)
当然,为类设置函数比较困难,但我确实使用std::function 来做到这一点。在PropertyFloat我有
typedef std::function<float(void)> GetterType;
所以它通过一个函数设置它,我将传递第一个 std::bind 作为参数显示
typename PropertyFloat::GetterType getter
当然,这些类型可以使用模板并更通用,但这取决于您的开发目标。
【讨论】:
std::mem_fn 和std::bind 进行这种事情将近两年了,虽然没有任何问题。
mem_fn 和bind 最复杂的用法之一。如果你想练习使用这两种类型,也许你应该看看它们的一些小用法(我在开发这个系统之前就做过)。这个反射系统是围绕这两种类型(和std::function)的使用而构建的。虽然老实说,这可能只是用成员函数指针替换(理论上)。它们各有优缺点。
通常,将成员函数用于回调可能会很麻烦,例如在<algorithm> 函数中使用。 std::mem_fn(现在已经标准化,因此您不再需要使用 tr1 命名空间)创建一个可调用对象,该对象可用作这些函数的函子对象。有关其使用示例,请参阅使用 std::string::size 的 this link 的示例部分。
std::bind 可以用于例如您在编译时不知道实际参数,但必须创建一个带有参数运行时的可调用对象。它也可以用于重新排序参数,例如:
auto f1 = std::bind(printf, _2, _1);
f1(42, "%d\n");
(好吧,愚蠢的例子,但我现在能想到的。)
【讨论】:
以下代码计算大于五的元素个数:
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
using namespace std;
vector<int> v { 1, 5, 2, 7, 6, 7, 5 };
cout << count_if(v.begin(), v.end(),
bind(greater<int>(), placeholders::_1, 5)) << endl;
}
【讨论】:
一个问题是 lambda 很难使用前向声明的类中的方法。我使用 bind 来使用使用前向声明类中的方法的成员函数。我找不到使用 lambda 的解决方案。场景如下:我有一个在类 A 中定义的成员函数 f1、f2、... 的列表,其中一些使用了前向声明类中的方法。我希望能够使用这些 fi 函数中的任何一个灵活地交换表达式树 B 类节点的运算符。在 B 中,定义了一个通用运算符。我使用 bind 将 fi 函数自适应地关联到通用运算符。这样,fi 成员函数定义可以在放置前向声明的 A.h 文件中进行原型化,然后可以将 fi 函数的实现放在 A.cpp 文件中并由 B 类访问。我很好奇其他人是否遇到过这个问题以及他们是如何处理的。
【讨论】: