如果我们不想将每个元素转换为一个转换元素,我们如何使用std :: transform?

时间:2015-04-25 14:22:55

标签: c++ c++11 stl iterator

如果我们不想将每个元素转换为一个转换元素,我们如何使用std::transform,但两个

以下伪代码说明了我想要实现的目标

std::transform(a.cbegin(), a.cend(), std::back_inserter(b), [](T const& x) {
    return f(x) and g(x);
});

当然,我可以两次调用std::transform,但那会很烦人。也许我们需要提供自定义插件。还有其他选择吗?

2 个答案:

答案 0 :(得分:6)

transform仅用于进行一对一转换。自定义插入器无法帮助您,因为transform的实现方式如下:

while (first1 != last1) {
    *d_first++ = unary_op(*first1++); // you have no way to write
                                      // more than one element
}
return d_first;

您实际上必须为a编写一个自定义迭代器来迭代每个元素两次,然后在您的仿函数中保持状态以了解您是否处于f状态或{{ 1}}状态。你可以看到它有多复杂。

除了简单的1-1转换之外,你应该只使用g循环:

for

即使对于简单的1-1转换,我认为一个简单的for (const auto& x : a) { b.push_back(f(x)); b.push_back(g(x)); } 表达式也会获胜。

您还可以编写自己的range-for,其中包含任意数量的仿函数:

transform

用;

template <typename InIt, typename OutIt, typename... Functors>
void transform(InIt first, InIt last, OutIt d_first, Functors... fs)
{
    while (first != last) {
        apply(*first, d_first, fs...);
        first++;
    }
}

用作(example):

template <typename In, typename OutIt>
void apply(const In&, OutIt ) { }

template <typename In, typename OutIt, typename F, typename... Functors>
void apply(const In& in, OutIt& out, F f, Functors... fs)
{
    *out++ = f(in);
    apply(in, out, fs...);
}

答案 1 :(得分:0)

通常在这种情况下,您可以使用标头std::accumulate中声明的标准算法<numeric>

例如

#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
#include <type_traits>

int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    std::vector<int> v;
    v.reserve( 2 * std::extent<decltype( a )>::value );

    std::accumulate( std::begin( a ), std::end( a ),
                     std::back_inserter( v ),
                     []( auto it, auto x )
                     {
                        return *it++ = x * x, *it++ = x * x * x, it;  
                     } );

    auto it = v.begin();                     
    for ( int x : a )
    {
        std::cout << x << '\t' << *it++ << '\t';
        std::cout << *it++ << std::endl;
    }

    return 0;
}

程序输出

1   1   1
2   4   8
3   9   27
4   16  64
5   25  125
6   36  216
7   49  343
8   64  512
9   81  729
10  100 1000