Thread: pair type and operator>>

  1. #1
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38

    Question pair type and operator>>

    What's wrong about this source code?
    Code:
    #include <iostream>
    #include <vector>
    #include <iterator>
    
    using namespace std;
    
    int main()
    {
            pair<string, int> si;
            istream_iterator<decltype(si)> in(cin), eos;
            vector<decltype(si)> vsi;
    
            if(in != eos)
            {
                    vsi.push_back(*in);
                    ++in;
                    while(in != eos)
                    {
                            vsi.push_back(*in);
                            ++in;
                    }
            } else  {
                    cerr << "No data?!" << endl;    // no input! Warn the user
                    return EXIT_FAILURE;    // indicate failure
            }
    
            for(const auto& p : vsi)
                    cout << p.first << " " << p.second << endl;
    
            return EXIT_SUCCESS;
    }
    Error messages generated:
    Code:
    In file included from /usr/include/c++/4.9/iterator:66:0,
                     from test.cpp:9:
    /usr/include/c++/4.9/bits/stream_iterator.h: In instantiation of ‘void std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::_M_read() [with _Tp = std::pair<std::basic_string<char>, int>; _CharT = char; _Traits = std::char_traits<char>; _Dist = long int]’:
    /usr/include/c++/4.9/bits/stream_iterator.h:70:17:   required from ‘std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_iterator(std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type&) [with _Tp = std::pair<std::basic_string<char>, int>; _CharT = char; _Traits = std::char_traits<char>; _Dist = long int; std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type = std::basic_istream<char>]’
    test.cpp:16:39:   required from here
    /usr/include/c++/4.9/bits/stream_iterator.h:121:17: error: no match for ‘operator>>’ (operand types are ‘std::istream_iterator<std::pair<std::basic_string<char>, int> >::istream_type {aka std::basic_istream<char>}’ and ‘std::pair<std::basic_string<char>, int>’)
          *_M_stream >> _M_value;
                     ^
    /usr/include/c++/4.9/bits/stream_iterator.h:121:17: note: candidates are:
    In file included from /usr/include/c++/4.9/iostream:40:0,
                     from test.cpp:6:
    /usr/include/c++/4.9/istream:120:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__istream_type& (*)(std::basic_istream<_CharT, _Traits>::__istream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
           operator>>(__istream_type& (*__pf)(__istream_type&))
           ^
    /usr/include/c++/4.9/istream:120:7: note:   no known conversion for argument 1 from ‘std::pair<std::basic_string<char>, int>’ to ‘std::basic_istream<char>::__istream_type& (*)(std::basic_istream<char>::__istream_type&) {aka std::basic_istream<char>& (*)(std::basic_istream<char>&)}’
    /usr/include/c++/4.9/istream:124:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__ios_type& (*)(std::basic_istream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>; std::basic_istream<_CharT, _Traits>::__ios_type = std::basic_ios<char>]
           operator>>(__ios_type& (*__pf)(__ios_type&))
           ^
    It looks like that the pair type has not overloaded the operator>>.
    Am I right? If true, is there a rationale behind this choice? Possible workarounds? TIA
    Best regards

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by frank67
    It looks like that the pair type has not overloaded the operator>>.
    Am I right?
    Yes.

    Quote Originally Posted by frank67
    If true, is there a rationale behind this choice?
    I do not know what is the rationale of the standard committee, but it is no big deal: after all, in practice input/output for a pair of objects might be delimited by various separators (e.g., commas, semi-colons, colons, equal signs, dashes, etc), not just whitespace, so chances are you want to customise how the pair is to be read anyway.

    Quote Originally Posted by frank67
    Possible workarounds?
    Define a struct with two members (or a single std::pair<std::string, int> member) and overload operator>> for it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2015
    Location
    Italy
    Posts
    38
    Do you mean that way?
    Code:
    #include <iostream>
    #include <vector>
    #include <iterator>
    
    using namespace std;
    
    struct istream_si
    {
    friend  istream& operator>>(istream&, istream_si&);
    friend  ostream& operator<<(ostream&, const istream_si&);
            istream_si(const string& s = string(), const int i = 0): si_pair({s, i}) { }
    private:
            pair<string, int> si_pair;
    };
    
    istream& operator>>(istream& is, istream_si& item)
    {
            is >> item.si_pair.first >> item.si_pair.second;
            if(!is)
                    item=istream_si("", 0);
            return is;
    }
    
    ostream& operator<<(ostream& os, const istream_si& item)
    {
            os      << item.si_pair.first   << " "
                    << item.si_pair.second  << flush;
            return os;
    }
    
    int main()
    {
            istream_si si;
            istream_iterator<decltype(si)> in(cin), eos;
            vector<decltype(si)> vsi;
    
            if(in != eos)
            {
                    vsi.push_back(*in);
                    ++in;
                    while(in != eos)
                    {
                            vsi.push_back(*in);
                            ++in;
                    }
            } else  {
                    cerr << "No data?!" << endl;    // no input! Warn the user
                    return EXIT_FAILURE;    // indicate failure
            }
    
            for(const auto& p : vsi)
                    cout << p << endl;
    
            return EXIT_SUCCESS;
    }
    I can't use template because not yet covered in the exercises series. I still don't understand why operator<< and operator>> aren't provided for pair class template, I saw that other operators (<,>,==,!=) exist since c++14 maybe they will be added in near future. Thanks again
    Best regards

  4. #4
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I wouldn't bet on them adding operator << or operator >> in the future. I would bet money against it.

    The way that you are using pairs right now, the first member and second member are separated by white space. In reality though, what separates the first and second members is an arbitrary choice.

    It's not done because whatever the standards committee would decide would become a new convention, and there are several existing and useful conventions today, already like:
    • Time - hh:mm
    • Day - dd/mm or mm/dd
    • Cartesian coordinates
    • Cookies are written as a series of key=value pairs separated by semicolons.


    Since it is so easy to just write code around doing the right thing with the pair, not supplying operator >> and operator << turns out to make std::pair easier to work with.
    Last edited by whiteflags; 02-18-2016 at 07:18 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Modulous Operator in Double type
    By r@k33n in forum C Programming
    Replies: 1
    Last Post: 04-23-2012, 04:23 AM
  2. Replies: 2
    Last Post: 05-23-2011, 02:04 PM
  3. define operator<< for std::pair<string, int>
    By patiobarbecue in forum C++ Programming
    Replies: 2
    Last Post: 02-07-2009, 08:29 AM
  4. reference operator following return type?
    By thracian in forum C++ Programming
    Replies: 22
    Last Post: 07-10-2008, 12:15 AM
  5. Operator= overloading from another type
    By g4j31a5 in forum C++ Programming
    Replies: 4
    Last Post: 10-04-2006, 08:15 PM