Compilation error due to ambiguous overload when using enums withtemplates

P

puzzlecracker

Guys, I get the following error when running the program below:

[ ~/c++]$ g++ TemplateEnumTypes.cpp
TemplateEnumTypes.cpp: In function `std::eek:stream& operator<<
(std::eek:stream&,
const E&) [with E = ElementType]':
TemplateEnumTypes.cpp:61: instantiated from here
TemplateEnumTypes.cpp:34: ambiguous overload for `std::eek:stream& <<
const
char[6]' operator
/usr/include/c++/3.2.3/bits/ostream.tcc:171: candidates are:
std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT,
_Traits>::eek:perator<<(long int) [with _CharT = char, _Traits =
std::char_traits<char>] <near match>


Here is the simple program:



#include<iostream>
#include<string>

using namespace std;


template< class E > struct EnumNames
{
static const char* const* names;
static int names_size;
};


#define REGISTER_ENUM( e ) \
const char* const* EnumNames< e >::names = e ## _names; \
int EnumNames< e >::names_size = sizeof( e ## _names ) / sizeof( const
char* );

enum ElementType { NEURON, SYNAPSE };
const char* const ElementType_names[] = { "N", "S" };
REGISTER_ENUM( ElementType )

enum TokenMainType { EP, IP, NT, AI };
const char* const TokenMainType_names[] = { "EP", "IP", "NT", "AI" };
REGISTER_ENUM( TokenMainType )

template<class E>
ostream& operator <<(ostream& os, const E& e)
{
if (e > EnumNames< E >::names_size)
cerr << "Error" << endl;
os << EnumNames< E >::names[e];
return os;

}

template<class E>
istream& operator >>(istream& is, E& e) {
std::string tmp_e_string;
is >> tmp_e_string;
for (int i = 0; i < EnumNames< E >::names_size; ++i) {
if (tmp_e_string == EnumNames< E >::names)
{
e = E(i);
return is;
}

}
cerr << "Fehler: tmp_nntype_string: " << tmp_e_string << endl;
return is;

}


int main (int argc, char **argv)
{
ElementType test1(NEURON);
cout<<test1<<endl;

return 0;
}
 
P

puzzlecracker

That's going to catch lots of stuff you don't want.  For each enumerated
type T you're trying to output, create a Formatted<T> that converts T to
string correctly, along with a dedicated overload of operator<<.

You can force operator<<(std::eek:stream&, Formatted<T>) to be instantiated
  automatically along with Formatted<T> (and therefore considered in
overload resolution) by declaring it a friend of Formatted<T>, right in
the Formatted<T> class body.  That's called "friend name injection."

A quick web-search shows that "friend name injection" is out of fashion,
but I'm not sure what the alternative would be here.

This is pretty popular pattern that I've outline above, I wonder how
other programmers are implementing it. References and examples would
be are highly appreciated.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top