【发布时间】:2014-12-29 18:25:19
【问题描述】:
我的问题的简短版本是这样的:如何将std::bind() 之类的东西与标准库算法一起使用?
由于简短版本有点缺乏细节,这里有点解释:假设我有算法std::transform(),现在我想实现std::copy()(是的,我意识到有std::copy()在标准 C++ 库中)。由于我非常懒惰,我显然想使用std::transform() 的现有实现。当然,我可以这样做:
struct identity {
template <typename T>
auto operator()(T&& value) const -> T&& { return std::forward<T>(value); }
};
template <typename InIt, typename OutIt>
auto copy(InIt begin, InIt end, OutIt to) -> OutIt {
return std::transform(begin, end, to, identity());
}
不知何故,这个实现有点像算法的配置。例如,似乎std::bind() 应该能够完成这项工作,但仅仅使用std::bind() 是行不通的:
namespace P = std::placeholders;
auto copy = std::bind(std::transform, P::_1, P::_2, P::_3, identity());
问题在于编译器不能仅从算法中确定适当的模板参数,是否存在& 无关紧要。有什么东西可以使使用std::bind() 之类的方法起作用吗?由于这是前瞻性的,我很高兴有一个解决方案可以处理已经提议包含在 C++ 标准中的任何内容。此外,为了摆脱我的懒惰,我很乐意在前面做一些工作,以便以后使用。可以这样想:作为库实施者,我将把所有东西放在一起,这样每个库用户都可以偷懒:我是一个忙碌的实施者但是一个懒惰的用户。
如果您想要一个现成的测试台:这里有一个完整的程序。
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <utility>
#include <vector>
using namespace std::placeholders;
struct identity {
template <typename T>
T&& operator()(T&& value) const { return std::forward<T>(value); }
};
int main()
{
std::vector<int> source{ 0, 1, 2, 3, 4, 5, 6 };
std::vector<int> target;
#ifdef WORKS
std::transform(source.begin(), source.end(), std::back_inserter(target),
identity());
#else
// the next line doesn't work and needs to be replaced by some magic
auto copy = std::bind(&std::transform, _1, _2, _3, identity());
copy(source.begin(), source.end(), std::back_inserter(target));
#endif
std::copy(target.begin(), target.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}
【问题讨论】:
-
@πάνταῥεῖ:嘿 - 这是一个真正的问题......! (当然,双重目标确实起作用)
-
标签组合是什么让我怀疑 ;-) ...(当然这是个好问题)
-
通用 lambdas 几乎是我唯一能想到的,但我认为这还不够
bind-like... -
您一定听说过 C++14 技术通过泛型 lambda 传递重载集。这种方法有什么问题或不足?
-
@dyp: 你想使用宏吗?啧啧……!但是,是的,这更接近我的想法。另外,我目前正在尝试完成类似的工作,但我使用的实现似乎对转发占位符并不完全满意。