c++ - 为什么C++标准库中没有transform_if?

标签 c++ c++-standard-library stl-algorithm

当想要进行连续复制时出现了一个用例(1. 可以使用 copy_if)但是从值的容器到指向这些值的指针的容器(2. 可以使用 变换)。

我无法使用可用的工具do it不到两步:

#include <vector>
#include <algorithm>

using namespace std;

struct ha { 
    int i;
    explicit ha(int a) : i(a) {}
};

int main() 
{
    vector<ha> v{ ha{1}, ha{7}, ha{1} }; // initial vector
    // GOAL : make a vector of pointers to elements with i < 2
    vector<ha*> ph; // target vector
    vector<ha*> pv; // temporary vector
    // 1. 
    transform(v.begin(), v.end(), back_inserter(pv), 
        [](ha &arg) { return &arg; }); 
    // 2. 
    copy_if(pv.begin(), pv.end(), back_inserter(ph),
        [](ha *parg) { return parg->i < 2;  }); // 2. 

    return 0;
}

当然,我们可以在 pv 上调用 remove_if 并消除对临时的需要,但更好的是,implement 并不难(对于一元操作)是这样的:

template <
    class InputIterator, class OutputIterator, 
    class UnaryOperator, class Pred
>
OutputIterator transform_if(InputIterator first1, InputIterator last1,
                            OutputIterator result, UnaryOperator op, Pred pred)
{
    while (first1 != last1) 
    {
        if (pred(*first1)) {
            *result = op(*first1);
            ++result;
        }
        ++first1;
    }
    return result;
}

// example call 
transform_if(v.begin(), v.end(), back_inserter(ph), 
[](ha &arg) { return &arg;      }, // 1. 
[](ha &arg) { return arg.i < 2; });// 2.
  1. 可用的 C++ 标准库工具是否有更优雅的解决方法?
  2. 库中不存在 transform_if 是否有原因?现有工具的组合是否是一种足够的解决方法和/或被认为表现良好?

最佳答案

标准库偏爱基本算法。

如果可能,容器和算法应该相互独立。

同样,可以由现有算法组成的算法很少被包括在内,作为简写。

如果你需要一个转换 if,你可以简单地编写它。如果您希望/today/组成现成的而不产生开销,您可以使用具有 惰性范围 的范围库,例如 Boost.Range ,例如:

v | filtered(arg1 % 2) | transformed(arg1 * arg1 / 7.0)

正如@hvd 在评论中指出的那样,transform_if double 会导致不同的类型(在本例中为 double)。组合顺序很重要,使用 Boost Range 你也可以这样写:

 v | transformed(arg1 * arg1 / 7.0) | filtered(arg1 < 2.0)

导致不同的语义。这让我们明白了这一点:

it makes very little sense to include std::filter_and_transform, std::transform_and_filter, std::filter_transform_and_filter etc. etc. into the standard library.

查看示例 Live On Coliru

#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>

using namespace boost::adaptors;

// only for succinct predicates without lambdas
#include <boost/phoenix.hpp>
using namespace boost::phoenix::arg_names;

// for demo
#include <iostream>

int main()
{
    std::vector<int> const v { 1,2,3,4,5 };

    boost::copy(
            v | filtered(arg1 % 2) | transformed(arg1 * arg1 / 7.0),
            std::ostream_iterator<double>(std::cout, "\n"));
}

关于c++ - 为什么C++标准库中没有transform_if?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23579832/

相关文章:

c++ - STL算法的可组合性

c++ - 并行 STL 是否处理插入迭代器,例如 std::back_insert_iterator?

c++ - 在非唯一集合上使用 erase-remove 习语

c++ - 这个预定义函数降低了我程序的性能

c++ - <algorithm> 是否包含 <cmath>?

c++ - GCC 链接器找不到标准库?

c++ - omn​​iORB C++ 服务器,运行应用程序的 Java 客户端问题

c++ - 当 std::uint_fast32_t 在 GCC 中为 4 字节时,std::mt19937 失败

c++ - vector::引用

c++ - 具有 const 参数的模板未按预期分派(dispatch)