concatenate vector returned from function

hello!
I have this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
class Foo{
public:
    int n;

    std::vector<Foo> subdivide(){
        std::vector<Foo> v(2, Foo());
        v[0].n = n/2-1;
        v[1].n = n/2+1;
        return v;
    }
};

int main(){
    std::vector<Foo> vec;
    Foo f;
    f.n = 10;
    vec.push_back(f);
    vec.insert(vec.end(), vec[0].subdivide());
}


well, it doesn't works, since insert needs two iterators as 2nd and 3rd arguments, and I'm giving only a full copy of a vector (as far as I understand). but is there any way to append the returned vector from the subdivide function to vec?

the only way I could think is like this:
1
2
std::vector<Foo> temp_vec = vec[0].subdivide();
    vec.insert(vec.end(), temp_vec.begin(), temp_vec.end());


but it seems weird, I create another vector just for this. is there any better way (aka one liner)?

thanks in advance
Alas, there is not. Make a function to help.

Approach 1: modify the argument vector

1
2
3
4
5
6
template <typename T>
std::vector <T> & concat( std::vector <T> & to, const std::vector <T> & from )
{
    to.insert( to.end(), from.begin(), from.end() );
    return to;
}

Now you can get your one-liner:

 
    concat( vec, vec[0].subdivide() );


Approach 2: make life pretty and let the compiler deal with optimizations

1
2
3
4
5
6
7
template <typename T>
std::vector <T> concat( const std::vector <T> & a, const std::vector <T> & b )
{
    std::vector <T> result{ a };
    result.insert( result.end(), b.begin(), b.end() );
    return result;
}

And the one-liner:

 
    vec = concat( vec, vec[0].subdivide() );

There are plenty of other ways as well, including just using a temporary:

1
2
3
4
    {
        auto v = vec[0].subdivide();
        vec.insert( vec.end(), v.begin(), v.end() );
    }

Hope this helps.
Heh, sorry, I wanted to play with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iomanip>
#include <iostream>
#include <memory>
#include <vector>

// Some operator magic ----------------------------------------------------------------------------

template <typename T, typename Allocator>
std::vector <T, Allocator> &
operator += ( std::vector <T, Allocator> & a, const std::vector <T, Allocator> & b )
{
  a.insert( a.end(), b.begin(), b.end() );
  return a;
}

template <typename T, typename Allocator>
std::vector <T, Allocator>
operator + ( const std::vector <T, Allocator> & a, const std::vector <T, Allocator> & b )
{
  auto   result  = a;
  return result += b;
}

// Tests ------------------------------------------------------------------------------------------

std::vector <int> f()
{
  return { 2, 4, 6, 8 };
}

int main()
{
  std::vector <int> xs{ 2, 3, 5, 7, 11 };

  std::cout << "xs:       ";              for (int x : xs)        std::cout << " " << x;  std::cout << "\n";
  std::cout << "xs + f(): ";              for (int x : xs + f())  std::cout << " " << x;  std::cout << "\n";
  std::cout << "xs:       ";              for (int x : xs)        std::cout << " " << x;  std::cout << "\n";
  std::cout << "xs += f():";  xs += f();  for (int x : xs)        std::cout << " " << x;  std::cout << "\n";
  std::cout << "xs:       ";              for (int x : xs)        std::cout << " " << x;  std::cout << "\n";
}

Using the two operator functions above, you can easily, now, say:

1
2
3
4
5
6
7
8
9
10
11
int main(){
    std::vector<Foo> vec;
    Foo f;
    f.n = 10;
    vec.push_back(f);
    vec += vec[0].subdivide();

    // let's see it!
    for (const auto& foo : vec)
      std::cout << foo.n << "\n";
}

Enjoy!
thaaanks! I'm not really used to templates, so besides the solution to the initial problem, now I have some good examples of using it :D
Thanks again!
Topic archived. No new replies allowed.