Initializing/Filling container with sample of another

I have a vector that I want to use to source another vector, something like copy_if, but without the need to allocate space first:

1
2
3
4
5
6
7
8
bool is_odd( const int x ){ return x % 2 == 1; }

std::vector< int > numbers = { 1, 2, 3, 4, 5, 6 };
std::vector< int > odd_numbers;

std::sweet_function( numbers.begin(), numbers.end(), odd_numbers, is_odd );

// odd_numbers is { 1, 3, 5 } 


Thanks


Even better might be a std::transform_if
Last edited on
you could copy_if into a back_inserter(odd_numbers)

as for transform_if, http://stackoverflow.com/questions/23579832/why-is-there-no-transform-if-in-stl
Last edited on
Thanks. I guess it's simple enough to write it myself. I was having trouble passing a lamda to a function, so I was trying to think of other ways to do it. Turns out my problem was right in front of my eyes the whole time.

Starting to have some fun with this one :)

Is it possible to get the vector out of lines 2 and 4? To be able to derive the container type from Cont?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>

template < typename Cont, typename Filt, typename Tran >
auto filter( Cont& cnt, Filt func, Tran tran ) -> std::vector< decltype( tran(cnt[0] ) ) >
{
  std::vector< decltype( tran( cnt[0] ) ) > ret;
  for ( auto& item : cnt ) if ( func( item ) ) ret.push_back( tran( item ) );
  return ret;
}

int main( void )
{
  std::vector< int > numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  auto is_odd = []( const int x ) { return x % 2 == 1; };

  auto transform = []( int& x ){ return &x; };

  auto odd_numbers = filter( numbers, is_odd, transform );

  for ( const auto& odd_number : odd_numbers )
    std::cout << *odd_number << '\n';
}


https://ideone.com/qfVaqe

Although, maybe simpler to just call std::transform and then std::remove_if...
Last edited on
Whats wrong with the copy_if method Cubbi suggested? It's certainly less complicated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include<vector>
#include <algorithm>
#include <iterator>

int main() {
	std::vector< int > numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto is_odd = [](int x){ return x % 2; };
	
	std::vector<int> odds;
	std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(odds), is_odd);

	for(auto a : odds)
		std::cout << a << ' ';
}
http://ideone.com/UzB9kP
Yes, sorry. I wasn't being clear about what I was trying to do. In fact, my question was about an alternative way to do the thing I needed.

Cubbi's suggestion works great, and it is what I would have done if I couldn't have gotten the thing I was originally trying to do working.

I was also hoping for a std container constructor that could take a predicate:
std::vector<int> odd_numbers( numbers.begin(), numbers.end(), is_odd );

However, my actual problem is that I want there to be a transform along with the copy. I don't want to be calling a copy-constructor of my object during the operation, so I want a vector<int*>

Edit: Now I want to try to get the vector out of line 2 and 4 of the code I posted, just for fun.

Isn't there a syntax something like:
template < typename T template < typename U, typename V >>
Which might help me?
Last edited on
The nicest solution I can think of is really boost.range from that Stackoverflow link.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <vector>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>

using boost::adaptors::filtered;
int main()
{
  std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  auto is_odd = [](int x){ return x % 2 == 1; };
  copy(numbers | filtered(is_odd), std::ostream_iterator<int>(std::cout, "\n"));
}


http://coliru.stacked-crooked.com/a/c67e156769fc6685

PS: oh, as for deducing "vector" in your code, you could try something like
1
2
3
4
5
6
7
8
9
template <template<typename...> class ContainerTT, typename ValueT, typename Filt, typename Tran >
auto filter( ContainerTT<ValueT>& cnt, Filt func, Tran tran ) -> ContainerTT< decltype( tran(cnt[0] ) ) >
{
  ContainerTT<decltype(tran(cnt[9]))> ret;
  for ( auto& item : cnt )
      if ( func( item ) )
          ret.push_back( tran( item ) );
  return ret;
}

http://coliru.stacked-crooked.com/a/f9c0024e59706b67
Last edited on
Topic archived. No new replies allowed.