problem with operator<<

Discussion in 'C++' started by Karl, Jan 18, 2006.

  1. Karl

    Karl Guest

    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!
    Karl, Jan 18, 2006
    #1
    1. Advertising

  2. Karl wrote:
    > 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
    Thomas Tutone, Jan 18, 2006
    #2
    1. Advertising

  3. Karl

    Mike Wahler Guest

    "Karl" <> wrote in message
    news:...
    > 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
    Mike Wahler, Jan 18, 2006
    #3
  4. Karl

    Mark P Guest

    Karl wrote:
    > 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
    Mark P, Jan 18, 2006
    #4
  5. Mark P wrote:
    > 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
    Thomas Tutone, Jan 18, 2006
    #5
  6. Karl

    Karl Guest

    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!
    Karl, Jan 19, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jakob Bieling

    Q: operator void* or operator bool?

    Jakob Bieling, Mar 5, 2004, in forum: C++
    Replies:
    2
    Views:
    562
    Rob Williscroft
    Mar 5, 2004
  2. John Smith
    Replies:
    2
    Views:
    415
    Ivan Vecerina
    Oct 6, 2004
  3. Afshin
    Replies:
    0
    Views:
    286
    Afshin
    Aug 12, 2011
  4. Afshin
    Replies:
    0
    Views:
    289
    Afshin
    Aug 12, 2011
  5. Afshin
    Replies:
    7
    Views:
    419
    Victor Bazarov
    Aug 16, 2011
Loading...

Share This Page