0

If we have

std::set<int > a;
std::vector<std::unordered_set<int>> b;

And we went to insert a inside b

Method 1: we can do:

std::set<int > a;
std::vector<std::unordered_set<int>> b (a.begin(), a.end());

Method 2, we cannot do this?

std::set<int > a;
std::vector<std::unordered_set<int>> b;
b.insert(a.begin(), a.end()); 

What does this error means?

error C2664: 'std::_Vector_iterator,std::equal_to<_Kty>,std::allocator<_Kty>>>>> std::vector,std::equal_to<_Kty>,std::allocator<_Kty>>,std::allocator<_Ty>>::insert(std::_Vector_const_iterator,std::equal_to<_Kty>,std::allocator<_Kty>>>>>,unsigned int,const _Ty &)' : cannot convert argument 1 from 'std::_Tree_const_iterator>>' to 'std::_Vector_const_iterator,std::equal_to<_Kty>,std::allocator<_Kty>>>>>' IntelliSense: no instance of overloaded function "std::vector<_Ty, _Alloc>::insert [with _Ty=std::unordered_set, std::equal_to, std::allocator>, _Alloc=std::allocator, std::equal_to, std::allocator>>]" matches the argument list argument types are: (std::_Tree_const_iterator>>, std::_Tree_const_iterator>>) object type is: std::vector, std::equal_to, std::allocator>, std::allocator, std::equal_to, std::allocator>>>

What is the solution if we need to deal with b as global unordered_set?

Sandy
  • 101
  • 1
  • 11

2 Answers2

4

For method 1, you can to it as below:

std::set<int> a{ 1, 2, 3, 4, 5};
std::vector<std::unordered_set<int>> b(1, std::unordered_set<int>(a.begin(), a.end()));

LIVE DEMO

For method two you can do as:

std::set<int> a{ 1, 2, 3, 4, 5};
std::vector<std::unordered_set<int>> b(1);
b[0].insert(a.begin(), a.end());

LIVE DEMO

Or alternatively as:

std::set<int> a{ 1, 2, 3, 4, 5};
std::vector<std::unordered_set<int>> b;
b.push_back({a.begin(), a.end()});

LIVE DEMO

Or alternatively as @Ben Voigt suggested:

  std::set<int> a{ 1, 2, 3, 4, 5};
  std::vector<std::unordered_set<int>> b;
  b.emplace_back(a.begin(), a.end());

LIVE DEMO

Community
  • 1
  • 1
101010
  • 41,839
  • 11
  • 94
  • 168
  • 1
    It works a lot like `push_back`, except it avoids making an extra copy of the element being added. – Ben Voigt Jun 19 '14 at 22:25
  • @BenVoigt I know it takes as input an `rvalue` reference but I'm not sure if it works with initializers. – 101010 Jun 19 '14 at 22:28
  • 1
    It doesn't need to work with initializer lists, all arguments are forwarded. – Ben Voigt Jun 19 '14 at 22:29
  • @BenVoigt I tried to do it and I'm getting an error http://coliru.stacked-crooked.com/a/b90c39609aec6f64, I found this relevant question: http://stackoverflow.com/questions/20391632/how-to-use-stdvectoremplace-back-for-vectorvectorint – 101010 Jun 19 '14 at 22:38
  • `b.emplace_back(a.begin(), a.end());` works for me. As I said, all arguments are forwarded, they don't need to be put into an initializer list. – Ben Voigt Jun 19 '14 at 22:43
  • @BenVoigt Yes you are right, I totally forgot about the ranged `emplace_back` :), thanks a lot. – 101010 Jun 19 '14 at 22:51
  • It's not "ranged". It's not emplacing multiple elements. It's emplacing one element, constructed by forwarding all arguments. – Ben Voigt Jun 19 '14 at 22:52
2

For method 2:

No overload of vector::insert() takes two iterators. Try this instead:

b.insert( b.begin(), { a.begin(), a.end() } )
yizzlez
  • 8,757
  • 4
  • 29
  • 44
  • Shouldn't that be `b.insert( b.begin(), { a.begin(), a.end() } )` since the `a` iterators define a single element (a set of int) to be inserted? – Ben Voigt Jun 19 '14 at 21:41
  • @BenVoigt I'm following this overload: `template< class InputIt > void insert( iterator pos, InputIt first, InputIt last);` – yizzlez Jun 19 '14 at 21:43
  • You can't do that. `*first` is an `int`, but the vector doesn't contain `int`, it contains `unordered_set`. – Ben Voigt Jun 19 '14 at 21:45