如果我们不想将每个元素转换为一个转换元素,我们如何使用std::transform
,但两个?
以下伪代码说明了我想要实现的目标
std::transform(a.cbegin(), a.cend(), std::back_inserter(b), [](T const& x) {
return f(x) and g(x);
});
当然,我可以两次调用std::transform
,但那会很烦人。也许我们需要提供自定义插件。还有其他选择吗?
答案 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