How can we use std :: transform if we do not want to convert each element into one transformed element, and two?

How can we use std::transform if we do not want to convert each element into one transformed element, but two?

The following pseudo code illustrates what I want to achieve

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

Of course, I could call std::transform twice, but that would be annoying. Maybe we need to provide a special insert. Any other option?

+6
source share
2 answers

transform is for one-to-one conversion only. Custom insertion will not help you, as transform implemented something like this:

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

In fact, you need to write your own iterator for a to repeat each element twice, and then save the state in your functor to find out if you are in state f or state g . You can see how difficult it is.

Anything other than simple 1-1 conversions, you should just use the for loop:

 for (const auto& x : a) { b.push_back(f(x)); b.push_back(g(x)); } 

And even for simple 1-1 conversions, I think that a simple range-for expression wins too.

You can optionally write your own transform , which takes an arbitrary number of functors:

 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++; } } 

with;

 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...); } 

used as ( example ):

 transform(a.begin(), a.end(), back_inserter(b), f, g); 
+6
source

Usually in such cases, you can use the standard std::accumulate algorithm declared in the <numeric> header.

for instance

 #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; } 

Program exit

 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 
0
source

Source: https://habr.com/ru/post/985947/


All Articles