Connecting Tech Pros Worldwide Forums | Help | Site Map

overloading << for map and multimap simultaneously

ozizus
Guest
 
Posts: n/a
#1: Jul 29 '07
I overloaded operator << for STL map successfully:

template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}

the code works like a charm. Now, I want the same functionality for
multimap. Since their interface is same for the problem at hand, I
want to make collection name a template parameter like this:

template <typename MAP, typename T1, typename T2ostream & operator
<< (ostream & o, MAP<T1,T2& m)
{
//code
}

The compiler errors like this: syntax error : missing ')' before '<'

thx,
ozi.


Victor Bazarov
Guest
 
Posts: n/a
#2: Jul 29 '07

re: overloading << for map and multimap simultaneously


ozizus wrote:
Quote:
I overloaded operator << for STL map successfully:
>
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}
>
the code works like a charm. Now, I want the same functionality for
multimap. Since their interface is same for the problem at hand, I
want to make collection name a template parameter like this:
>
template <typename MAP, typename T1, typename T2ostream & operator
<< (ostream & o, MAP<T1,T2& m)
{
//code
}
>
The compiler errors like this: syntax error : missing ')' before '<'
The compiler cannot deduce all three from the argument you give.
Besides, if 'MAP' is a template (as you imply by using the template
syntax when declaring the second argument), then it's not a "typename"
argument, it's a "template <class,classclass MAP" argument. Try

template<template<class, classclass MAP, typename T1, typename T2>
ostream& operator << (...

but it is most likely not going to work. I recommend dropping the T1
and T2 arguments and just do

template<class MAPostream& operator <<( ostream& o, MAP const& m)

(you do want to have the output object 'const', by the way).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


Kai-Uwe Bux
Guest
 
Posts: n/a
#3: Jul 29 '07

re: overloading << for map and multimap simultaneously


ozizus wrote:
Quote:
I overloaded operator << for STL map successfully:
>
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}
>
the code works like a charm. Now, I want the same functionality for
multimap. Since their interface is same for the problem at hand, I
want to make collection name a template parameter like this:
>
template <typename MAP, typename T1, typename T2ostream & operator
<< (ostream & o, MAP<T1,T2& m)
{
//code
}
>
The compiler errors like this: syntax error : missing ')' before '<'
a) technically, you want something like:

template < template <class, class class MAP, typename T1, typename T2 >

Read up on template template parameters (as opposed to typename template
parameters).

b) Using a template template parameter here, is a BadIdea(tm) since your
template would match too many things, e.g., it would match a pair<S,T>. In
that case, your code will not work.

Thus: you should just do another template for multimaps.

c) You may want to make your code aware of the Allocator and Comparison
typename parameters in the map template. I.e.,

template< typename S, typename T, typename A, typename C >
std::ostream & operator<< ( std::ostream & ostr,
const std::multimap< S, T, A, C & v );



Best

Kai-Uwe Bux
terminator
Guest
 
Posts: n/a
#4: Jul 29 '07

re: overloading << for map and multimap simultaneously


On Jul 29, 4:00 pm, ozizus <o...@ce.yildiz.edu.trwrote:
Quote:
I overloaded operator << for STL map successfully:
>
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
>
}
>
the code works like a charm. Now, I want the same functionality for
multimap. Since their interface is same for the problem at hand, I
want to make collection name a template parameter like this:
>
template <typename MAP, typename T1, typename T2ostream & operator
<< (ostream & o, MAP<T1,T2& m)
{
//code
>
}
>
The compiler errors like this: syntax error : missing ')' before '<'
>
thx,
ozi.
you can simply write:

template<typename MapT>
ostream & operator << (ostream & o, const MapT& m){
typedef typename MapT::Key_type T1;
typedef typename MapT::mapped_type T2;
//code

return o;
};


if your compiler supports concepts ,things will be easier :

auto concept map_like <MapT>{//what a (multi)map looks like.
typedef typename MapT::key_type key_type;
typedef typename MapT::mapped_type mapped_type;
//etc:

};

template<map_like MapT>//argument type must behave like a map
ostream & operator << (ostream & o, const MapT& m){
//code

return o;
};


regards,
FM.

ozizus
Guest
 
Posts: n/a
#5: Jul 29 '07

re: overloading << for map and multimap simultaneously


Quote:
a) technically, you want something like:
>
template < template <class, class class MAP, typename T1, typename T2 >
>
Read up on template template parameters (as opposed to typename template
parameters).
I tried the code below, but got error C2065: 'T2' : undeclared
identifier.

template<template<class,classclass MAP, typename T1, typename t2>
ostream & operator << (ostream & o, MAP<T1,T2& m)

C++ is huge, is not it, lots of reading up to do.. Thx anyway.

ozizus
Guest
 
Posts: n/a
#6: Jul 29 '07

re: overloading << for map and multimap simultaneously


>
Quote:
template<typename MapT>
ostream & operator << (ostream & o, const MapT& m){
typedef typename MapT::Key_type T1;
typedef typename MapT::mapped_type T2;
//code
>
return o;
>
};
>
template<typename MapTostream & operator << (ostream & o, MapT & m)
{
typedef typename MapT::key_type T1;
typedef typename MapT::mapped_type T2;
...
}

gives the cute one liner below:

error LNK2019: unresolved external symbol "class
std::basic_ostream<char,struct std::char_traits<char & __cdecl
operator<<<class std::vector<int,class std::allocator<int,class
std::map<class std::vector<int,class std::allocator<int,int,struct
std::less<class std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int (class
std::basic_ostream<char,struct std::char_traits<char &,class
std::map<class std::vector<int,class std::allocator<int,class
std::map<class std::vector<int,class std::allocator<int,int,struct
std::less<class std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int >,struct std::less<class
std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,class std::map<class
std::vector<int,class std::allocator<int,int,struct std::less<class
std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int &)" (??$?6V?$vector@HV?
$allocator@H@std@@@std@@V?$map@V?$vector@HV?$alloc ator@H@std@@@std@@HU?
$less@V?$vector@HV?$allocator@H@std@@@std@@@2@V?$a llocator@U?$pair@$
$CBV?$vector@HV?$allocator@H@std@@@std@@H@std@@@2@ @1@@@YAAAV?
$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ AAV?$map@V?
$vector@HV?$allocator@H@std@@@std@@V?$map@V?$vecto r@HV?
$allocator@H@std@@@std@@HU?$less@V?$vector@HV?
$allocator@H@std@@@std@@@2@V?$allocator@U?$pair@$$ CBV?$vector@HV?
$allocator@H@std@@@std@@H@std@@@2@@2@U?$less@V?$ve ctor@HV?
$allocator@H@std@@@std@@@2@V?$allocator@U?$pair@$$ CBV?$vector@HV?
$allocator@H@std@@@std@@V?$map@V?$vector@HV?$alloc ator@H@std@@@std@@HU?
$less@V?$vector@HV?$allocator@H@std@@@std@@@2@V?$a llocator@U?$pair@$
$CBV?$vector@HV?$allocator@H@std@@@std@@H@std@@@2@ @2@@std@@@2@@1@@Z)
referenced in function _main


MSVS2005, seems like no concepts. Thx anyway.


Kai-Uwe Bux
Guest
 
Posts: n/a
#7: Jul 29 '07

re: overloading << for map and multimap simultaneously


ozizus wrote:
Quote:
>
Quote:
>a) technically, you want something like:
>>
> template < template <class, class class MAP, typename T1, typename T2
Quote:
> >
>>
>Read up on template template parameters (as opposed to typename template
>parameters).
>
I tried the code below, but got error C2065: 'T2' : undeclared
identifier.
You have a typo:
Quote:
template<template<class,classclass MAP, typename T1, typename t2>
^^
Quote:
ostream & operator << (ostream & o, MAP<T1,T2& m)
^^


Also: make that a MAP<T1,T2const & m.
^^^^^

Also: don't do this anyway. I already explained why it is a bad idea.

If you want to avoid code duplication, implement a template

template < typename Cont >
std::ostream & write_sequence ( std::ostream & os, Cont const & c )

and use it to implement output for map and multimap.

Quote:
C++ is huge, is not it, lots of reading up to do.. Thx anyway.
True.


Best

Kai-Uwe Bux
James Kanze
Guest
 
Posts: n/a
#8: Jul 29 '07

re: overloading << for map and multimap simultaneously


On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz.edu.trwrote:
Quote:
I overloaded operator << for STL map successfully:
Quote:
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}
Quote:
the code works like a charm.
Are you sure? In what namespace did you put it? If you put it
in std, then you have undefined behavior. And if you put it in
some other namespace, if you use it in a template, the compiler
will only find it when it is instantiated on a class in the same
namespace (dependant name look-up oblige).

In general, you can't reliably overload operator<< generically
for any of the container types in the standard library (nor can
you overload it for instantiations where only standard types are
involved). In general, of course, you don't want to either.

--
James Kanze (Gabi Software) email: james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

ozizus
Guest
 
Posts: n/a
#9: Jul 30 '07

re: overloading << for map and multimap simultaneously


On Jul 29, 10:34 pm, James Kanze <james.ka...@gmail.comwrote:
Quote:
On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz.edu.trwrote:
>
Quote:
I overloaded operator << for STL map successfully:
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}
the code works like a charm.
>
Are you sure? In what namespace did you put it?
I put it in no namespace. I use "using namespace std;". This may be
bad practice but it works. Since I overloaded << for other containers,
I can output any object that is a combination of these containers in
one line. Same is true for >too.

eg.
map<vector<int>, set<string>m;
//code
cout<<m;

very powerfull.

terminator
Guest
 
Posts: n/a
#10: Jul 30 '07

re: overloading << for map and multimap simultaneously


On Jul 29, 6:28 pm, ozizus <o...@ce.yildiz.edu.trwrote:
Quote:
Quote:
template<typename MapT>
ostream & operator << (ostream & o, const MapT& m){
typedef typename MapT::Key_type T1;
typedef typename MapT::mapped_type T2;
//code
>
Quote:
return o;
>
Quote:
};
>
template<typename MapTostream & operator << (ostream & o, MapT & m)
{
typedef typename MapT::key_type T1;
typedef typename MapT::mapped_type T2;
..
>
}
>
gives the cute one liner below:
>
error LNK2019: unresolved external symbol "class
std::basic_ostream<char,struct std::char_traits<char & __cdecl
operator<<<class std::vector<int,class std::allocator<int,class
std::map<class std::vector<int,class std::allocator<int,int,struct
std::less<class std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int (class
std::basic_ostream<char,struct std::char_traits<char &,class
std::map<class std::vector<int,class std::allocator<int,class
std::map<class std::vector<int,class std::allocator<int,int,struct
std::less<class std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int >,struct std::less<class
std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,class std::map<class
std::vector<int,class std::allocator<int,int,struct std::less<class
std::vector<int,class std::allocator<int >,class
std::allocator<struct std::pair<class std::vector<int,class
std::allocator<int const ,int &)" (??$?6V?$vector@HV?
$allocator@H@std@@@std@@V?$map@V?$vector@HV?$alloc ator@H@std@@@std@@HU?
$less@V?$vector@HV?$allocator@H@std@@@std@@@2@V?$a llocator@U?$pair@$
$CBV?$vector@HV?$allocator@H@std@@@std@@H@std@@@2@ @1@@@YAAAV?
$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ AAV?$map@V?
$vector@HV?$allocator@H@std@@@std@@V?$map@V?$vecto r@HV?
$allocator@H@std@@@std@@HU?$less@V?$vector@HV?
$allocator@H@std@@@std@@@2@V?$allocator@U?$pair@$$ CBV?$vector@HV?
$allocator@H@std@@@std@@H@std@@@2@@2@U?$less@V?$ve ctor@HV?
$allocator@H@std@@@std@@@2@V?$allocator@U?$pair@$$ CBV?$vector@HV?
$allocator@H@std@@@std@@V?$map@V?$vector@HV?$alloc ator@H@std@@@std@@HU?
$less@V?$vector@HV?$allocator@H@std@@@std@@@2@V?$a llocator@U?$pair@$
$CBV?$vector@HV?$allocator@H@std@@@std@@H@std@@@2@ @2@@std@@@2@@1@@Z)
referenced in function _main
>
That looks like a multiple definition error.try defining some
function :

ostream& out(mytype& m,ostream& os);
Quote:
MSVS2005, seems like no concepts. Thx anyway.
no surprize it is too new and for ms2005.

MSVC supports templates as arguments but I did not want to suggest
that.As long as (multi)map takes 4 type arguments(last two have
default params) you will need five arguments for such a template:

#define T typename
template< template <T,T,T,TT MapT/*0*/,T Key/*1*/, T Value/*2*/,T
Predicate/*3*/,T Alloc/*4*/>
ostream& (ostream& os, MapT<Key,Value,Predicate,Alloc& m);

on MSVS (multi)map/set derive from 'template<typename traitsstruct
_Tree' defined in <xtreeheader.you can overload for '_Tree' but that
affects (multi)set as well(potentially more classes):

#include<xtree>
using namespace std;
template <typename traits>
ostream& (ostream& os, _Tree<traits& m);

regards,
FM.

James Kanze
Guest
 
Posts: n/a
#11: Jul 31 '07

re: overloading << for map and multimap simultaneously


On Jul 30, 12:39 pm, ozizus <o...@ce.yildiz.edu.trwrote:
Quote:
On Jul 29, 10:34 pm, James Kanze <james.ka...@gmail.comwrote:
Quote:
On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz.edu.trwrote:
Quote:
Quote:
Quote:
I overloaded operator << for STL map successfully:
template <typename T1, typename T2ostream & operator << (ostream &
o, map <T1,T2& m)
{
//code
}
the code works like a charm.
Quote:
Quote:
Are you sure? In what namespace did you put it?
Quote:
I put it in no namespace. I use "using namespace std;". This may be
bad practice but it works.
No it doesn't. (I mean putting your operator in no namespace.)
Try something like:

std::copy(
c.begin(), c.end(),
std::ostream_iterator< std::map< X, Y ( std::cout,
"\n" ) ) ;

Your operator won't be found, unless either X or Y are user
defined types in the same namespace as your operator.
Quote:
Since I overloaded << for other containers,
I can output any object that is a combination of these containers in
one line. Same is true for >too.
Quote:
eg.
map<vector<int>, set<string>m;
//code
cout<<m;
Quote:
very powerfull.
Very unmaintainable, you mean. Not something you really want to
do; it's a definite recepe for undefined behavior.

The answer to your question is simple: there's no way to define
an overload of operator<< for a standard type in a way that is
guaranteed to work in all cases, and you don't want to, even if
you could.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Closed Thread


Similar C / C++ bytes