By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,515 Members | 1,848 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,515 IT Pros & Developers. It's quick & easy.

Problem with defining operator<< for std::ostream_iterator

P: n/a
I cannot compile the code which defines a std::map type consisting of
built in types and operator<< overload for std::map::value_type.
See the code below - I attach a full example.

Note: if I define map type with my new type (structure) everything is
OK. All compileres I've cheked report an error so I think it is a
problem with my code.

#include <algorithm>
#include <cstddef>
#include <fstream>
#include <iterator>
#include <map>

class A
{
struct S // behavior similar to built-in int
{
int i;
S( int _i ) : i( _i ) {}
};

typedef std::map< int, int Map1;
typedef std::map< int, S Map2;

// the function below cannot be found by
std::ostream_iterator< Map1::value_type >
friend std::ostream &operator<<( std::ostream &_ostr, const
Map1::value_type &_value )
{
return _ostr << _value.first << ' ' << _value.second;
}

friend std::ostream &operator<<( std::ostream &_ostr, const
Map2::value_type &_value )
{
return _ostr << _value.first << ' ' << _value.second.i;
}

Map1 m_map1;
Map2 m_map2;

public:
A(
const int *_keyStart,
const int *_valueStart,
const std::size_t _size
)
{
for ( std::size_t i = 0; i < _size; i++ )
{
m_map1.insert( Map1::value_type( _keyStart[i], _valueStart[i] ) );
m_map2.insert( Map2::value_type( _keyStart[i],
S( _valueStart[i] ) ) );
}
}

~A()
{
std::ofstream out( "test" );

out << "#### Map1 ####" << std::endl;
// this call does not compile
std::copy(
m_map1.begin(),
m_map1.end(),
std::ostream_iterator< Map1::value_type >( out, "\n" )
);

out << "\n#### Map2 ####" << std::endl;
std::copy(
m_map2.begin(),
m_map2.end(),
std::ostream_iterator< Map2::value_type >( out, "\n" )
);
}
};

int main()
{
int tab1[] = { 1, 3, 5, 2, 0 };
int tab2[ sizeof tab1 / sizeof *tab1 ] = { 1, 2, 3, 4, 5 };

A a( tab1, tab2, sizeof tab1 / sizeof *tab1 );
}

May 30 '07 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On 30 Maj, 09:03, krzysztof.kono...@gmail.com wrote:
I cannot compile the code which defines a std::map type consisting of
built in types and operator<< overload for std::map::value_type.
See the code below - I attach a full example.

Note: if I define map type with my new type (structure) everything is
OK. All compileres I've cheked report an error so I think it is a
problem with my code.

#include <algorithm>
#include <cstddef>
#include <fstream>
#include <iterator>
#include <map>

class A
{
struct S // behavior similar to built-in int
{
int i;
S( int _i ) : i( _i ) {}
};

typedef std::map< int, int Map1;
typedef std::map< int, S Map2;

// the function below cannot be found by
// std::ostream_iterator< Map1::value_type >
friend std::ostream &operator<<(
std::ostream &_ostr,
const Map1::value_type &_value
)
{
return _ostr << _value.first << ' ' << _value.second;
}
The type of Map1::value_type is int which means that you are trying to
overload the operator
std::ostream &operator<<(std::ostream&, int)
To overload an operator at least one of the operands needs to be of
user-defined type (which is why it works with the second one).

--
Erik Wikström

May 30 '07 #2

P: n/a

Erik Wikström napisa³(a):
>
The type of Map1::value_type is int which means that you are trying to
overload the operator
std::ostream &operator<<(std::ostream&, int)
To overload an operator at least one of the operands needs to be of
user-defined type (which is why it works with the second one).

--
Erik Wikström
No, 'Map1::value_type' is of type 'std::pair< const int, int >', not
'int', so I am trying to define function:
std::ostream &operator<<( std::ostream&, const std::pair< const int,
int & )

If your statement would be true I got compilation error that
std::ostream &operator<<(std::ostream&, int) is already defined but I
didn't. My problem is that std::ostream_iterator< Map1::value_type >
cannot find my definition of operator<<().

If I write the code below everything is OK (it can find my definition
of operator<<() )
for ( Map1::const_iterator it = m_map1.begin(); it != m_map1.end(); it+
+ )
logfile << *it << std::endl;

May 30 '07 #3

P: n/a
kr***************@gmail.com wrote :
I cannot compile the code which defines a std::map type consisting of
built in types and operator<< overload for std::map::value_type.
See the code below - I attach a full example.

Note: if I define map type with my new type (structure) everything is
OK. All compileres I've cheked report an error so I think it is a
problem with my code.

[.. snip ..]

class A
{
struct S // behavior similar to built-in int
{
int i;
S( int _i ) : i( _i ) {}
};

typedef std::map< int, int Map1;
typedef std::map< int, S Map2;

friend std::ostream &operator<<( std::ostream &_ostr, const
Map1::value_type &_value )
{
return _ostr << _value.first << ' ' << _value.second;
}
Try not to define the operator<<() inside A. While the definition of
operator<<() injects that function in the enclosing namespace, it is
still in the lexical scope of the class itself, and it will therefore
not be found during overload resolution. The reason that it works when
you use 'A' or 'S' as template arguments for the map, your class *is*
searched because of ADL, and the correct operator<<() is found.

- Sylvester
May 30 '07 #4

P: n/a

Sylvester Hesp napisa (a):
Try not to define the operator<<() inside A. While the definition of
operator<<() injects that function in the enclosing namespace, it is
still in the lexical scope of the class itself, and it will therefore
not be found during overload resolution. The reason that it works when
you use 'A' or 'S' as template arguments for the map, your class *is*
searched because of ADL, and the correct operator<<() is found.

- Sylvester
Yes, I thought that ADL is reason in this case but I want to keep Map1
typedef private in class A so it implies operator<<() to be a friend
of class A.
Moreover, I need to declare operator<<() in std namespace.

Of course, there are work-arounds:
- use loop instead of std::copy and std::ostream_iterator
- make Map1 typedef public and define operator<<() in std namespace

I prefer first solution but it fits only the simple example I
provided. The main problem is still unresolved so I think I need to
dig in and understand ADL deeper and find a solution.

Thanks

May 30 '07 #5

P: n/a
kr***************@gmail.com wrote :
Sylvester Hesp napisa (a):
>Try not to define the operator<<() inside A. While the definition of
operator<<() injects that function in the enclosing namespace, it is
still in the lexical scope of the class itself, and it will therefore
not be found during overload resolution. The reason that it works when
you use 'A' or 'S' as template arguments for the map, your class *is*
searched because of ADL, and the correct operator<<() is found.

- Sylvester

Yes, I thought that ADL is reason in this case but I want to keep Map1
typedef private in class A so it implies operator<<() to be a friend
of class A.
Moreover, I need to declare operator<<() in std namespace.
Yes indeed, I didn't even think of that.
>
Of course, there are work-arounds:
- use loop instead of std::copy and std::ostream_iterator
- make Map1 typedef public and define operator<<() in std namespace
And obviously:
- Use a user defined type that behaves like another (built-in) type,
like your 'A::S'.

I think I personally prefer that solution - you don't have to put
anything into the std namespace and you don't impose certain standard
unspecified behaviour with the standard types. What if another
programmer in your project tries to do something similar to what you're
doing? That is impossible because you have already put a definition for
operator<<(std::map<int,int>) in the std namespace.

By using a custom type you keep things private to your class.

- Sylvester
May 30 '07 #6

This discussion thread is closed

Replies have been disabled for this discussion.