1

I have an input of:

1 a
2 b
..

I would like to insert them to a vector of pairs, with copy function, like this:

#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>

int main(void) {
    std::vector<std::pair<int, char>> v;
    std::copy(std::istream_iterator<std::pair<int, char>>(std::cin), std::istream_iterator<std::pair<int, char>>(), std::back_inserter(v));
    for(auto pair: v)
        std::cout << pair.first << std::endl;
    return 0;
}

However, this will not compile: error: no match for 'operator>>', since it probably needs an operator overloading.

Does that mean that I will have to create my own class, which inhertis from std::vector, and then overload the operator?

I would like to avoid using my own class, instead of the standard vector class.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • You need to define your own implementation for `<<` to read a pair [like this may be](http://rextester.com/ATHMY25752) – P0W Oct 23 '17 at 06:50
  • Oh @P0W, so the issue with the iterator, not the vector, I see! – gsamaras Oct 23 '17 at 06:52
  • Nah I'm little hesitant in doing/suggesting in `std` namespace. There are better alternatives, which might need little more efforts. – P0W Oct 23 '17 at 06:55

2 Answers2

2

The problem is not with std::vector, it's std::istream_iterator. The reason being that std::pair doesn't have a deserialization operator defined.

You can still use std::vector and std::back_insert_iterator, but you'll need to define your own input iterator. One that reads pairs of values.

Some people may suggest that you define operator>> for your pairs, but that is an unreliable technique. It will depend on the operator being defined before you include <algorithm> and <iterator>.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Ah I see, +1! Could you explain your last paragraph? – gsamaras Oct 23 '17 at 06:53
  • 1
    @gsamaras - [This is why](https://stackoverflow.com/questions/46811833/why-does-stdlesseigenvectorxd-fail-to-compile/46812491#46812491). The code your were offered in the comment to your post re-opens namesapce std. We can't do that to add definitions of new functions. It's UB. – StoryTeller - Unslander Monica Oct 23 '17 at 06:55
1

You could copy it through a proxy object:

#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>

struct proxy
{
    friend auto operator>>(std::istream& is, proxy& prox) -> std::istream&
    {
        is >> std::get<0>(prox.target);
        is >> std::get<1>(prox.target);
        return is;
    }

    operator std::pair<int, char>() const {
        return target;
    }

    std::pair<int, char> target;
};

int main(void) {
    std::vector<std::pair<int, char>> v;
    std::copy(std::istream_iterator<proxy>(std::cin), 
              std::istream_iterator<proxy>(), 
              std::back_inserter(v));
    for(auto pair: v)
        std::cout << pair.first << std::endl;
    return 0;
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • Nice answer. I would accept it if it stated that my impression of what should be overloaded was wrong (it's the iterator, not the vector). So that the accepted answer would be compact. – gsamaras Oct 23 '17 at 08:22