Overloading istream_iterator ---- cannot bind lvalue to 'std :: basic_istream <char> &&
I have done some research, for example:
- Overload operator <: cannot bind lvalue to 'std :: basic_ostream &&
- Overload operator <: cannot bind 'std :: basic_ostream lvalue with' std :: basic_ostream &&
- error: cannot bind 'std :: basic_ostream lvalue to' std :: basic_ostream &&
Tell me if I misunderstood some.
I tried to enter std :: pair from a file and I wanted to use std :: istream_iterator>
Here is the code:
std::ifstream in("file.in"); std::map<int, int> pp; pp.insert((std::istream_iterator<std::pair<int, int> >(in)), std::istream_iterator<std::pair<int, int> >()); I did the overload as follows:
std::istream & operator>>(std::istream & in, std::pair<int, int> & pa) { in >> pa.first >> pa.second; return in; } std::istream & operator>>(std::istream && in, std::pair<int, int> & pa) { in >> pa.first >> pa.second; return in; } Here's the error:
In file included from /usr/include/c++/4.8/iterator:66:0, from No_12.cpp:7: /usr/include/c++/4.8/bits/stream_iterator.h: In instantiation of 'void std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::_M_read() [with _Tp = std::pair<int, int>; _CharT = char; _Traits = std::char_traits<char>; _Dist = long int]': /usr/include/c++/4.8/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<int, int>; _CharT = char; _Traits = std::char_traits<char>; _Dist = long int; std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type = std::basic_istream<char>]' No_12.cpp:23:59: required from here /usr/include/c++/4.8/bits/stream_iterator.h:121:17: error: cannot bind 'std::istream_iterator<std::pair<int, int> >::istream_type {aka std::basic_istream<char>}' lvalue to 'std::basic_istream<char>&&' *_M_stream >> _M_value; ^ In file included from /usr/include/c++/4.8/iostream:40:0, from /files/Nutstore/000/CPPWorkSpace/SHUCourse/DataStructures/BinarySearchTree/20130514/src/BinarySearchTree.hpp:6, from /files/Nutstore/000/CPPWorkSpace/SHUCourse/DataStructures/BinarySearchTree/20130514/BinarySearchTree:3, from No_12.cpp:1: /usr/include/c++/4.8/istream:872:5: error: initializing argument 1 of 'std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&&, _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::pair<int, int>]' operator>>(basic_istream<_CharT, _Traits>&& __is, _Tp& __x) I do not know what I can do now ... I hope someone can give me some advice. Thanks.
To understand what the problem is, we need to look at an example implementation of istream_iterator (the problem arises from the requirements of the Standard, which are implicitly shown here):
template < class T, class CharT, class Traits, class Distance > class istream_iterator { /* ... */ typedef std::basic_istream<CharT, Traits> istream_type; istream_type* stored_istream_ptr; T value; public: /* ... */ istream_iterator& operator++() { *stored_istream_ptr >> value; // (A) return *this; } T const& operator*() const { return value; } /* ... */ }; In line (A), the operator is applied to objects of dependent types:
valueis of typeTstored_istream_ptris of typeistream_type, see typedef
According to [temp.dep.type] / 8, both types are dependent.
For the expression A >> B , as well as for any other function call, the function name is first looked at (here: operator>> ) β name search, then from the set of found functions (overloads), the most viable is selected and called β overload resolution.
For the operator, both member functions and non-member functions are searched (for example, your operators).
In this case, the types involved depend on it, therefore special rules are applied for searching name [temp.dep.res] / 1:
When resolving dependent names, names from the following sources are taken into account:
- Ads that are visible at the template definition point.
- Declarations from namespaces associated with function argument types both from the creation context (14.6.4.1) and from the definition context.
Your statements have been defined in a global namespace that is not associated with either std::basic_istream or std::pair . Therefore, resolving the name does not find your statements and overloading the expression in line (A) fails.
This explains the clang 3.2 error message:
stream_iterator.h: 120: 17: error: invalid operands for a binary expression ('istream_type' (aka 'basic_istream <char, std :: char_traits>') and 'std :: pair')
*_M_stream >> _M_value; ~~~~~~~~~~ ^ ~~~~~~~~
And that explains why workarounds work.
g ++, on the other hand, seems to show only one overload found by name resolution, and the reason why it rejects it (whereas clang ++ shows all overloads found by name resolution, for one reason for each of them, why it was rejected). One g ++ show might be the "best option":
template< class CharT, class Traits, class T > basic_istream<CharT,Traits>& operator>>(basic_istream<CharT,Traits>&&, T&); What is AFAIK, just a shell to call another operator>> in the case when the expression istream_obj >> value works on rvalue (for example, get_istream() >> value ).
This is not related to your problem (and confusing).
Two workarounds:
- use a wrapper type to wrap
std::pairso you can defineoperator>>in the namespace associated with that wrapper type - enter operators into the std namespace (not recommended)