problem with operator<<

K

Karl

Hey everyone!

So I'm writing my own String class to wrap std::string and implement an
API as close to identical as possible to the Java API. It's pretty
small so far:

#include <string>

class String
{
public:
String(std::string s) : mString(s)
{
}
String(const char* s) : mString(s)
{
}
String()
{
}
std::string& toStdString()
{
return mString;
}
const std::string& toStdString() const
{
return mString;
}
const char* toCString() const
{
return mString.c_str();
}
bool operator==(const String& s) const
{
return mString == s.mString;
}

private:
std::string mString;
};

Trying to use '<<' with a String results in the following predictable
result with g++:

error: no match for 'operator<<' in 'oss << s'

So, my String class became the following:

#include <ostream>
#include <string>

class String
{
public:
String(std::string s) : mString(s)
{
}
String(const char* s) : mString(s)
{
}
String()
{
}
std::string& toStdString()
{
return mString;
}
const std::string& toStdString() const
{
return mString;
}
const char* toCString() const
{
return mString.c_str();
}
bool operator==(const String& s) const
{
return mString == s.mString;
}

private:
std::string mString;

public:
friend std::eek:stream& operator<<(std::eek:stream& os, const String& s);
};

std::eek:stream& operator<<(std::eek:stream& os, const String& s)
{
os << s.mString;
return os;
}

But now I get the following very unpredictable result with g++:

multiple definition of `operator<<(std::basic_ostream<char,
std::char_traits<char> >&, String const&)'

I get this on line 40, which is the line 'std::eek:stream&
operator<<(std::eek:stream& os, const String& s)', the first line of the
definition.

Anyone have any ideas? Thanks ahead of time!
 
T

Thomas Tutone

Karl said:
Hey everyone!
[snip]

So, my String class became the following:

#include <ostream>
#include <string>

class String
{
public:
String(std::string s) : mString(s)
{
}
String(const char* s) : mString(s)
{
}
String()
{
}
std::string& toStdString()
{
return mString;
}
const std::string& toStdString() const
{
return mString;
}
const char* toCString() const
{
return mString.c_str();
}
bool operator==(const String& s) const
{
return mString == s.mString;
}

private:
std::string mString;

public:
friend std::eek:stream& operator<<(std::eek:stream& os, const String& s);
};

std::eek:stream& operator<<(std::eek:stream& os, const String& s)
{
os << s.mString;
return os;
}

But now I get the following very unpredictable result with g++:

multiple definition of `operator<<(std::basic_ostream<char,
std::char_traits<char> >&, String const&)'

I get this on line 40, which is the line 'std::eek:stream&
operator<<(std::eek:stream& os, const String& s)', the first line of the
definition.

Anyone have any ideas?

I'm not sure what the problem is, but I do have a potential solution.
Delete the friend declaration from your class definition. Then change
your operator<< definition to the following:

std::eek:stream& operator<<(std::eek:stream& os, const String& s)
{
os << s.toStdString();
return os;
}

I'm guessing this will eliminate the multiple definition error, and
also conforms your code to useful adage, "Don't grant friendship unless
there is a good reason to do so." In your code, there is no good
reason to do so.

Best regards,

Tom
 
M

Mike Wahler

Karl said:
Hey everyone!

So I'm writing my own String class to wrap std::string and implement an
API as close to identical as possible to the Java API. It's pretty
small so far:

#include <string>

class String
{
public:
String(std::string s) : mString(s)
{
}
String(const char* s) : mString(s)
{
}
String()
{
}
std::string& toStdString()
{
return mString;
}
const std::string& toStdString() const
{
return mString;
}
const char* toCString() const
{
return mString.c_str();
}
bool operator==(const String& s) const
{
return mString == s.mString;
}

private:
std::string mString;
};

Trying to use '<<' with a String results in the following predictable
result with g++:

error: no match for 'operator<<' in 'oss << s'

So, my String class became the following:

#include <ostream>
#include <string>

class String
{
public:
String(std::string s) : mString(s)
{
}
String(const char* s) : mString(s)
{
}
String()
{
}
std::string& toStdString()
{
return mString;
}
const std::string& toStdString() const
{
return mString;
}
const char* toCString() const
{
return mString.c_str();
}
bool operator==(const String& s) const
{
return mString == s.mString;
}

private:
std::string mString;

public:
friend std::eek:stream& operator<<(std::eek:stream& os, const String& s);
};

std::eek:stream& operator<<(std::eek:stream& os, const String& s)
{
os << s.mString;
return os;
}

But now I get the following very unpredictable result with g++:

multiple definition of `operator<<(std::basic_ostream<char,
std::char_traits<char> >&, String const&)'

I get this on line 40, which is the line 'std::eek:stream&
operator<<(std::eek:stream& os, const String& s)', the first line of the
definition.

Anyone have any ideas? Thanks ahead of time!

Is the above a header which you #include in more than one
source file? If so, that would be the cause of the error.
The defintion of the operator<< function should not be in a
header.

-Mike
 
M

Mark P

Karl said:
Hey everyone!

So I'm writing my own String class to wrap std::string and implement an
API as close to identical as possible to the Java API. It's pretty
small so far:

#include <string>

class String
{ ...
};

Trying to use '<<' with a String results in the following predictable
result with g++:

error: no match for 'operator<<' in 'oss << s'

So, my String class became the following:

#include <ostream>
#include <string>

class String
{ ...
friend std::eek:stream& operator<<(std::eek:stream& os, const String& s);
};

std::eek:stream& operator<<(std::eek:stream& os, const String& s)
{
os << s.mString;
return os;
}

But now I get the following very unpredictable result with g++:

multiple definition of `operator<<(std::basic_ostream<char,
std::char_traits<char> >&, String const&)'

I get this on line 40, which is the line 'std::eek:stream&
operator<<(std::eek:stream& os, const String& s)', the first line of the
definition.

Anyone have any ideas? Thanks ahead of time!

If you choose to define operator<< in a header then you need to declare
it inline (or move it to a file which is only processed once by the
compiler-- generally a .cpp file). Otherwise the linker will see the
function declared multiple times in different translation units and emit
the error you observed.

You should also be using include guards in your header files:

#ifndef MY_STRING_H
#define MY_STRING_H

[body of header goes here]

#endif
 
T

Thomas Tutone

Mark said:
If you choose to define operator<< in a header then you need to declare
it inline (or move it to a file which is only processed once by the
compiler-- generally a .cpp file). Otherwise the linker will see the
function declared multiple times in different translation units and emit
the error you observed.

You should also be using include guards in your header files:

#ifndef MY_STRING_H
#define MY_STRING_H

[body of header goes here]

#endif

To the OP - Mike W and Mark P raise a valid point (and probably the
correct explanation of your problem) - if your definition of operator<<
appears in a header file, you need to either move it out of the header
file (but leave a declaration), or else define it as inline. But I
would still recommend you get rid of the friend declaration in the
class, since it isn't needed here.

Best regards,

Tom
 
K

Karl

Thanks everyone! I had this weird macro-header setup going, which
confused me entirely so I decided to scrap it. Everything's fine now.
Thanks!
 

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,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top