6

My question is simple, see example:

std::array<int,6> a = {{0,1,2,3,4,5}}; // -- given container. auto F = []( int i ) { return i*i; }; // -- given function. std::vector<int> v; // need create // my solution: v.reserve( a.size () ); for( std::size_t i = 0; i < a.size(); ++i ) v.push_back( F(a[i]) ); // but I need something like std::vector<int>v( a.begin(), a.end(), <|applying each element to F|> ); 

Can I create container something like above not calling reserve explicitly and any reallocation?

EDIT:

  1. I want avoid reserve; because othercase my first solution is good for me :)
  2. I want avoid any resize; because it's initialzed each element by default ctor.
  3. I will use this in the real project which may included many 3-rd party libraries ( boost, Soft-STL, ...).
3
  • 6
    Will std::transform not do this? Commented Feb 21, 2014 at 19:22
  • transform iterators might be of use here. Commented Feb 21, 2014 at 19:23
  • I want avoid v.reserve(a.size()), also. Commented Feb 21, 2014 at 19:23

3 Answers 3

12

The standard algorithm std::transform does exactly this!

std::vector<int> v(a.size()); std::transform( std::begin(a), std::end(a), std::begin(v), F ); 

You can start with an empty vector and use std::back_inserter, if you like:

std::vector<int> v; std::transform( std::begin(a), std::end(a), std::back_inserter(v), F ); 

But you're subjecting yourself to needless re-allocations if you do that (unless you reserve first, as in your original attempt). You can decide for yourself what your priority is.

Sign up to request clarification or add additional context in comments.

12 Comments

I can't use v(a.size() ), because my real container element is not an int, some large class. and it's required me two lines.
@Khurshid: Sure, that's up to you. You have all options open to you here. What do you mean by requiring only two lines? Why? Space in source code is very cheap! :)
@Khurshid Still, a call to reserve + the bqck_inserter example seems like a fine option.
does back_inserter call push_back ? if yes, it's not efficient memory usafe.
I was want, more readability solution without any cost to performance. explicit writing reserve - isn't readable, only for performance.
|
5

Use std::transform:

#include <algorithm> // std::transform #include <iterator> // std::back_inserter .... transform(a.begin(), a.end(), back_inserter(v), F); 

You may want to call v.reserve(asize()) first to avoid re-allocations.

5 Comments

Insidious use of ADL.
@KerrekSB I was feeling particularly lazy. Friday is the new Sunday.
@KerrekSB What's ADL? :P
@herohuyongtao It's what makes the unqualified call back_inserter(v) work.
@Snps: And to transform
2

Another solution is to use boost::transform_iterator. The benefit is that you can pass iterators to the container constructor. That avoids memory reallocations compared to when using std::back_inserter or having to call reserve or resize on the destination. All in one statement:

std::vector<int> result( boost::make_transform_iterator(std::begin(a), F) , boost::make_transform_iterator(std::end(a), F) ); 

You can achieve terser syntax though, like this:

std::vector<int> result(transform_range(a, F)); 

transform_range implementation:

template<class Iterator> struct AutoSequence { Iterator const beg_, end_; template<class T> operator std::vector<T>() const { return {beg_, end_}; } }; template<class Function, class InSeq> auto transform_range(InSeq const& in) -> AutoSequence<decltype(boost::make_transform_iterator<Function>(in.begin()))> { return { boost::make_transform_iterator<Function>(std::begin(in)) , boost::make_transform_iterator<Function>(std::end(in)) }; } template<class Function, class InSeq> auto transform_range(InSeq const& in, Function&& f) -> AutoSequence<decltype(boost::make_transform_iterator(in.begin(), f))> { return { boost::make_transform_iterator(std::begin(in), f) , boost::make_transform_iterator(std::end(in), f) }; } 

11 Comments

Completely unnecessary use of third-party library. What does this give you? One line of code saved here, a thousand added in a header. Awesome.
@LightnessRacesinOrbit Cry me a river.
so, did you measure that performance benefit? and also did you measure compilation time impact?
@MaximYegorushkin: Aha! A rationale! It's a sound one, too, though you'd still have to try very hard to convince me that this tiny micro-optimisation is worth bringing in a third-party library to do the job. Your answer, unfortunately, doesn't make the OP aware of this whatsoever.
#define BOOST_RESULT_OF_USE_DECLTYPE need with lambda )
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.