Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

operator<< for pair

38 views
Skip to first unread message

Ahmet Can ÜN

unread,
Aug 7, 2016, 12:26:49 PM8/7/16
to
Hi,


I wanted to write the content of a std::map to a file. So i wrote
operator<< function for pairs.

But i'm getting an error.
#include <string>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <map>
#include <utility>
#include <iterator>

using namespace std;

template<typename T1, typename T2>
ofstream &operator<<(ofstream &os, pair<T1, T2> rp)
{
return os << " " << rp.first << " " << rp.second << '\n';
}

int main()
{
ifstream ifs("salk.txt");
map<string, int> smap;

string s;

while (ifs >> s)
++smap[s];

ofstream ofs("ahmet.txt");

copy(smap.begin(),
smap.end(),
ostream_iterator<map<string, int>::value_type>
(ofstream("ahmet.txt")));
return 0;

}

This is the error message.

binary '<<': no operator found which takes a right-hand operand of type
'const std::pair<const _Kty,_Ty>' (or there is no acceptable conversion)

When i try to write them to a file without using std::copy, i have no problem. The code below works fine.

ofs << make_pair("ahmet can", 3);

Öö Tiib

unread,
Aug 7, 2016, 2:22:34 PM8/7/16
to
On Sunday, 7 August 2016 19:26:49 UTC+3, Ahmet Can ÜN wrote:
> Hi,
>
>
> I wanted to write the content of a std::map to a file. So i wrote
> operator<< function for pairs.
>
> But i'm getting an error.
> #include <string>
> #include <iomanip>
> #include <iostream>
> #include <fstream>
> #include <map>
> #include <utility>
> #include <iterator>
>
> using namespace std;
>
> template<typename T1, typename T2>
> ofstream &operator<<(ofstream &os, pair<T1, T2> rp)
> {
> return os << " " << rp.first << " " << rp.second << '\n';
> }

Three problems:

1) The ostream reference that those operator<< that you call return is not
convertible to ofstream reference that you return.

2) The template is in global namespace but none of its operands is (both
are in namespace std) and so it won't be found by argument dependent
lookup.

3) the operator takes a pair by value that may mean some expensive copy
is made while all it needs is const& to pair.


That will likely work:

namespace std
{
template<typename T1, typename T2>
ostream& operator<<(ostream& os, pair<T1, T2> const& rp)
{
return os << " " << rp.first << " " << rp.second << '\n';
}
}


>
> int main()
> {
> ifstream ifs("salk.txt");
> map<string, int> smap;
>
> string s;
>
> while (ifs >> s)
> ++smap[s];
>
> ofstream ofs("ahmet.txt");
>
> copy(smap.begin(),
> smap.end(),
> ostream_iterator<map<string, int>::value_type>
> (ofstream("ahmet.txt")));
> return 0;
>
> }
>
> This is the error message.
>
> binary '<<': no operator found which takes a right-hand operand of type
> 'const std::pair<const _Kty,_Ty>' (or there is no acceptable conversion)
>
> When i try to write them to a file without using std::copy, i have no problem. The code below works fine.
>
> ofs << make_pair("ahmet can", 3);

Are you sure you replaced 'copy()' in *posted* code with that?
I think it can no way compile for reason 1) I gave. What compiler you
use?

Ahmet Can ÜN

unread,
Aug 7, 2016, 3:17:20 PM8/7/16
to
On Sunday, August 7, 2016 at 9:22:34 PM UTC+3, Öö Tiib wrote:
> On Sunday, 7 August 2016 19:26:49 UTC+3, Ahmet Can ÜN wrote:
> > Hi,
> >
> >
> > I wanted to write the content of a std::map to a file. So i wrote
> > operator<< function for pairs.
> >
> > But i'm getting an error.
> > #include <string>
> > #include <iomanip>
> > #include <iostream>
> > #include <fstream>
> > #include <map>
> > #include <utility>
> > #include <iterator>
> >
> > using namespace std;
> >
> > template<typename T1, typename T2>
> > ofstream &operator<<(ofstream &os, pair<T1, T2> rp)
> > {
> > return os << " " << rp.first << " " << rp.second << '\n';
> > }
>
> Three problems:
>
> 1) The ostream reference that those operator<< that you call return is not
> convertible to ofstream reference that you return.
>
> 2) The template is in global namespace but none of its operands is (both
> are in namespace std) and so it won't be found by argument dependent
> lookup.
>
> 3) the operator takes a pair by value that may mean some expensive copy

> Are you sure you replaced 'copy()' in *posted* code with that?
> I think it can no way compile for reason 1) I gave. What compiler you
> use?

I'm using microsoft visual c++. You are right i changed the return value of
the function before posting it here. Changing the return value to ostream &
was sufficient for this one liner.

ofs << make_pair("ahmet can", 3);

Why ADL didn't cause a problem for this one. pair is in the std namespace but the operator<< is not.

But for the std::copy, as you said i had to put the operator function in to std namespace, then it worked. I thought ADL is not limited to arguments namespace.

I wouldn't normally write a function template that takes a pair by value.
0 new messages