Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading >> ifstream_iterator for pairs [duplicate]

Tags:

c++

iterator

I am trying to construct an ifstream_iterator on pair. My code is as follows:

typedef pair<float, int> T;

istream& operator>>(istream& stream, T& in) {
    stream >> in.first >> in.second;
    return stream;
}


int main(int argc, char **argv) {
    ifstream infile("dummy2");
    istream_iterator<T> iit(infile);
    istream_iterator<T> eos;
    while (iit != eos) {
        cout << (*iit).first << endl;
        ++iit;
    }
    return 0;
}

I have a dummy file "dummy2" as follows:

"a" 4 "b" 5

I would like to output pairs {"a", 4} and {"b", 5}.

However, I get nasty compilation error

In file included from /usr/include/c++/4.6/iterator:66:0,
                 from filestream.cpp:9:
/usr/include/c++/4.6/bits/stream_iterator.h: In member function ‘void std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::_M_read() [with _Tp = std::pair<float, int>, _CharT = char, _Traits = std::char_traits<char>, _Dist = long int]’:
/usr/include/c++/4.6/bits/stream_iterator.h:70:9:   instantiated from ‘std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_iterator(std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type&) [with _Tp = std::pair<float, int>, _CharT = char, _Traits = std::char_traits<char>, _Dist = long int, std::istream_iterator<_Tp, _CharT, _Traits, _Dist>::istream_type = std::basic_istream<char>]’
filestream.cpp:32:33:   instantiated from here
/usr/include/c++/4.6/bits/stream_iterator.h:121:6: error: no match for ‘operator>>’ in ‘*((std::istream_iterator<std::pair<float, int> >*)this)->std::istream_iterator<std::pair<float, int> >::_M_stream >> ((std::istream_iterator<std::pair<float, int> >*)this)->std::istream_iterator<std::pair<float, int> >::_M_value’
/usr/include/c++/4.6/bits/stream_iterator.h:121:6: note: candidates are:
/usr/include/c++/4.6/istream:122: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>]
/usr/include/c++/4.6/istream:122:7: note:   no known conversion for argument 1 from ‘std::pair<float, 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.6/istream:126: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>]
/usr/include/c++/4.6/istream:126:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘std::basic_istream<char>::__ios_type& (*)(std::basic_istream<char>::__ios_type&) {aka std::basic_ios<char>& (*)(std::basic_ios<char>&)}’
/usr/include/c++/4.6/istream:133:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:133:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘std::ios_base& (*)(std::ios_base&)’
/usr/include/c++/4.6/istream:169:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(bool&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:169:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘bool&’
/usr/include/c++/4.6/istream:173:7: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(short int&) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.6/istream:173:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘short int&’
/usr/include/c++/4.6/istream:176:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(short unsigned int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:176:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘short unsigned int&’
/usr/include/c++/4.6/istream:180:7: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(int&) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.6/istream:180:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘int&’
/usr/include/c++/4.6/istream:183:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(unsigned int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:183:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘unsigned int&’
/usr/include/c++/4.6/istream:187:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:187:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘long int&’
/usr/include/c++/4.6/istream:191:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long unsigned int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:191:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘long unsigned int&’
/usr/include/c++/4.6/istream:196:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:196:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘long long int&’
/usr/include/c++/4.6/istream:200:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long long unsigned int&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:200:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘long long unsigned int&’
/usr/include/c++/4.6/istream:205:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(float&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:205:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘float&’
/usr/include/c++/4.6/istream:209:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(double&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:209:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘double&’
/usr/include/c++/4.6/istream:213:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(long double&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:213:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘long double&’
/usr/include/c++/4.6/istream:217:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(void*&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__istream_type = std::basic_istream<char>]
/usr/include/c++/4.6/istream:217:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘void*&’
/usr/include/c++/4.6/istream:241:7: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]
/usr/include/c++/4.6/istream:241:7: note:   no known conversion for argument 1 from ‘std::pair<float, int>’ to ‘std::basic_istream<char>::__streambuf_type* {aka std::basic_streambuf<char>*}’
/usr/include/c++/4.6/bits/basic_string.tcc:998:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::basic_string<_CharT, _Traits, _Alloc>&)
/usr/include/c++/4.6/bits/random.tcc:923:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::uniform_int_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:968:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::uniform_real_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:1890:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::cauchy_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.h:3381:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::bernoulli_distribution&)
/usr/include/c++/4.6/bits/random.tcc:1733:5: note: template<class _RealType1, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::normal_distribution<_RealType1>&)
/usr/include/c++/4.6/bits/random.tcc:1063:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::geometric_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:2085:5: note: template<class _RealType1, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::gamma_distribution<_RealType1>&)
/usr/include/c++/4.6/bits/random.tcc:1622:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::exponential_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:2143:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::weibull_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:2200:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::extreme_value_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:194:5: note: template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::linear_congruential_engine<_UIntType, __a, __c, __m>&)
/usr/include/c++/4.6/bits/random.tcc:491:5: note: template<class _UIntType, long unsigned int __w, long unsigned int __n, long unsigned int __m, long unsigned int __r, _UIntType __a, long unsigned int __u, _UIntType __d, long unsigned int __s, _UIntType __b, long unsigned int __t, _UIntType __c, long unsigned int __l, _UIntType __f, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>&)
/usr/include/c++/4.6/bits/random.tcc:642:5: note: template<class _UIntType, long unsigned int __w, long unsigned int __s, long unsigned int __r, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::subtract_with_carry_engine<_UIntType, __w, __s, __r>&)
/usr/include/c++/4.6/bits/random.tcc:709:5: note: template<class _RandomNumberEngine, long unsigned int __p, long unsigned int __r, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::discard_block_engine<_RandomNumberEngine, __p, __r>&)
/usr/include/c++/4.6/bits/random.tcc:815:5: note: template<class _RandomNumberEngine, long unsigned int __k, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::shuffle_order_engine<_RandomNumberEngine, __k>&)
/usr/include/c++/4.6/bits/random.tcc:1138:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::negative_binomial_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:1328:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::poisson_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:1577:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::binomial_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:1782:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::lognormal_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:1827:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::chi_squared_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:1936:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::fisher_f_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:1981:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::student_t_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:2308:5: note: template<class _IntType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::discrete_distribution<_IntType>&)
/usr/include/c++/4.6/bits/random.tcc:2488:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::piecewise_constant_distribution<_RealType>&)
/usr/include/c++/4.6/bits/random.tcc:2690:5: note: template<class _RealType, class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::piecewise_linear_distribution<_RealType>&)
/usr/include/c++/4.6/bits/istream.tcc:957:5: note: template<class _CharT2, class _Traits2> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT2*)
/usr/include/c++/4.6/bits/istream.tcc:925:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT&)
/usr/include/c++/4.6/istream:709:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char&)
/usr/include/c++/4.6/istream:714:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char&)
/usr/include/c++/4.6/istream:756:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char*)
/usr/include/c++/4.6/istream:761:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char*)
/usr/include/c++/4.6/istream:852:5: note: std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&&, _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = std::pair<float, int>] <near match>
/usr/include/c++/4.6/istream:852:5: note:   no known conversion for argument 1 from ‘std::istream_iterator<std::pair<float, int> >::istream_type {aka std::basic_istream<char>}’ to ‘std::basic_istream<char>&&’
/usr/include/c++/4.6/iomanip:70:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Resetiosflags)
/usr/include/c++/4.6/iomanip:100:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Setiosflags)
/usr/include/c++/4.6/iomanip:131:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Setbase)
/usr/include/c++/4.6/iomanip:169:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Setfill<_CharT>)
/usr/include/c++/4.6/iomanip:199:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Setprecision)
/usr/include/c++/4.6/iomanip:229:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Setw)
/usr/include/c++/4.6/iomanip:263:5: note: template<class _CharT, class _Traits, class _MoneyT> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::_Get_money<_MoneyT>)
make: *** [filestream] Error 1

I cannot quite make sense of what is happening here. Any help is appreciated. Thanks a lot!

like image 256
Myssa89 Avatar asked Jan 20 '15 20:01

Myssa89


2 Answers

You'll note that simply doing this:

T t;
infile >> t;

Works like a charm! What is up?

std::pair is declared in namespace std.

istream_iterator<> uses operator>> indeed, and it does so using ADL at instantiation time (this is known as two-phase-lookup).

However, at instantiation time, it will not consider your operator>> as it doesn't exist in the namespace that implements istream_iterator and neither was it declared in any of the associated namespaces implied by the arguments (this is the ADL step).

You could be tempted "fix" it by defining your overload in the std namespace (and it works) but that is not allowed by the standard and technically results in Undefined Behaviour.

So you'd do better to introduce a type that allows ADL to kick in:

struct T : public std::pair<int,float> {};

Live On Coliru

#include <utility>
#include <iostream>
#include <iterator>

struct T : std::pair<float, int> {
    using std::pair<float, int>::pair;
};

std::istream& operator>>(std::istream& stream, T& in) {
    return stream >> in.first >> in.second;
}

int main() {
    std::istream_iterator<T> iit(std::cin);
    std::istream_iterator<T> eos;
    while (iit != eos) {
        std::cout << (*iit).first << std::endl;
        ++iit;
    }
}

I suspect that theoretically you should be able to trick thing by reordering includes and injecting the overload early enough so it is "visible" during the first phase of name lookup. However, whether this option is available depends on the implementation and if you're out of luck you still couldn't achieve it without altering the standard library headers (don't do that).

like image 200
sehe Avatar answered Oct 26 '22 22:10

sehe


This is a fairly common problem, for which there's no really clean solution. One that normally works is to put your operator into namespace std:

typedef pair<float, int> T;

namespace std {
    istream& operator>>(istream& stream, T& in) {
        stream >> in.first >> in.second;
        return stream;
    }
}

int main(int argc, char **argv) {
    ifstream infile("dummy2");
    istream_iterator<T> iit(infile);
    istream_iterator<T> eos;
    while (iit != eos) {
        cout << (*iit).first << endl;
        ++iit;
    }
    return 0;
}

Officially, this gives undefined behavior--you can add some specializations to namespace std, but you can't add overloads there. Unofficially, I've yet to see a compiler/library where it caused a problem.

like image 32
Jerry Coffin Avatar answered Oct 26 '22 22:10

Jerry Coffin