考虑以下代码段:在一个第一类型T1的容器上进行迭代,以创建第二个第二类型T2的容器,应用转换函数T1-> T2,但仅用于验证谓词(T1-> bool)的T1元素< / p>
(在以下示例中为奇数)。
std::vector<int> myIntVector;
myIntVector.push_back(10);
myIntVector.push_back(15);
myIntVector.push_back(30);
myIntVector.push_back(13);
std::vector<std::string> myStringVectorOfOdd;
std::for_each(myIntVector.begin(), myIntVector.end(),
[&myStringVectorOfOdd](int val)
{
if (val % 2 != 0)
myStringVectorOfOdd.push_back(std::to_string(val));
});
我在这段代码中不喜欢的是lambda上的捕获。有没有一种方法可以将std :: copy_if和std :: transform结合起来,以更简洁明了的方式实现相同的结果?
答案 0 :(得分:7)
这里是一个transform_if
模板,它采用通常的输入迭代器对,输出迭代器和谓词以及转换函数对象。
template <class InputIt, class OutputIt, class Pred, class Fct>
void transform_if(InputIt first, InputIt last, OutputIt dest, Pred pred, Fct transform)
{
while (first != last) {
if (pred(*first))
*dest++ = transform(*first);
++first;
}
}
您可以将其用作示例,如下所示。
transform_if(myIntVector.cbegin(), myIntVector.cend(),
std::back_inserter(myStringVectorOfOdd),
[](int n){ return n % 2 != 0; },
[](int n){ return std::to_string(n); });
这不是超级简洁,但是过滤和转换被很好地分为了无捕获的lambda,并且算法本身习惯于在迭代器上工作。
由于范围库为组合算法提供了更好的支持,因此基于Boost range的范围库也是如此:
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
using boost::adaptors::filtered;
boost::transform(myIntVector | filtered([](int n){ return n % 2 != 0; }),
std::back_inserter(myStringVectorOfOdd), [](int n){ return std::to_string(n); });
答案 1 :(得分:4)