14 Replies - 2177 Views - Last Post: 01 December 2012 - 03:46 PM Rate Topic: -----

#1 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 06:19 AM

so pure for educational purposes I'm writing my own string class. when I wanted to overload the << operator to be able to use cout, I encounter errors. I tried googling it, but they all give the same answer, and that answer doesn't work for me.
so here's the code from the header:
friend std::ostream &operator<<(std::ostream &stream, const wString str);

and this one comes from the source file:
std::ostream& wString::operator<<(std::ostream &stream, const wString str)
{
  stream << str;
  return stream;  // return the stream
}

but this returns the following error:
/home/Jiro/projects/QT/Wlib/Wlib/wstring.cpp:105: error: 'std::ostream& wString::operator<<(std::ostream&, wString)' must take exactly one argument


or more detailed:
../Wlib/wstring.cpp:105:74: error: 'std::ostream& wString::operator<<(std::ostream&, wString)' must take exactly one argument
14:16:21: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project Wlib (target: Desktop)
When executing step 'Make'


if it's of any help, I'm using Qt Creator on openSuse 12.2

any help is appreciated.

Is This A Good Question/Topic? 0
  • +

Replies To: trouble overloading '<<' operator for custom string cl

#2 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 06:47 AM

Quote

I tried googling it, but they all give the same answer, and that answer doesn't work for me.

What is the answer they all give that is not right?

Have you tried using a const reference (const wString&) instead of the copy? It may also be a problem with the const.

Otherwise post the smallest complete program that illustrates your problem.

Jim

This post has been edited by jimblumberg: 24 November 2012 - 06:49 AM

Was This Post Helpful? 0
  • +
  • -

#3 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 06:59 AM

well basicly all the examples and snippets and explanations point to this example
and I can't provide a program, since I'm trying to create a library. if you want to I can provide the entire wString class, but I don't really see the point in that (excuse me my rudeness)
I've tried with const wString&, wString& and wString but none is working. the compiler keeps saying that it can only take one argument. but in the header it keeps saying that I need two arguments. I literally used the snippets from the internet and my book (adjusting myClass to wString and removing unexisting variables) but it keeps giving me this error. to be complete I'll provide the entire header and source.
header:
#ifndef WSTRING_H
#define WSTRING_H

#include "includes.h"

class wString
{
protected:
    //variables
    std::vector<char> data;
    //end of vars
public:
    //begin constructors

    wString();
    wString(char *c);
    wString(const std::string& str);
    wString(char c);
    ~wString(void);

    //end constructors

    //begin operators

    bool operator ==(wString& string);
    bool operator ==(std::string& string);
    bool operator ==(char* string);
    wString& operator +=(wString& string);
    wString& operator +=(std::string& string);
    wString& operator +=(char& c);
    wString operator +(wString& string);
    wString operator +(std::string& string);
    friend std::ostream &operator<<(std::ostream &stream,wString &str);
    char operator [](int& pos);

    //end of operators
    //functions

    std::string to_std_string(); //verander je wString in een normale C++ string
    char* to_c_string(); //verander je wString in een C-stijl string
    wString* split(const char c); //splits hem in meerdere Wstrings (*pointer to the array)
    int length(); //verkrijg de lengte van de wString
    bool empty(); //kijk na of er iets in de string zit
    wString& swap(wString& str); //verwissel de data van twee wStringen
    void Clear(); //maak de hele string leeg
    int Find(const char c);
    void Print();
    //end of functions
};
typedef wString Wstring;

#endif // WSTRING_H


source:
#include "wstring.h"
wString::wString()
{
}
wString::wString(char *c)
{
    std::string str = std::string(c); //std::string is easer to work trough
    for(unsigned i=0;i<str.length();i++) this->data.push_back(str[i]);
}
wString::wString(const std::string &str)
{
    for(unsigned i=0;i<str.length();i++) this->data.push_back(str[i]);
}
wString::wString(char c)
{
    this->data.push_back(c);
}

wString::~wString()
{
    this->data.clear();
}
bool wString::operator ==(wString& string)
{
    if(this->data == string.data) return true;
    else return false;
}
bool wString::operator ==(std::string& string)
{
    bool result = true;
    if(string.length() != this->data.size())result = false;
    if(result != false)
    {
        for(unsigned i=0;i<this->data.size();i++)
        {
            if(string[i] != this->data[i])
            {
                result = false;
                break; //one error is enough
            }
        }
    }
    return result;
}
bool wString::operator ==(char* string)
{
    bool result = true;
    if(sizeof(string) != this->data.size())result = false;
    if(result != false)
    {
        for(unsigned i=0;i<this->data.size();i++)
        {
            if(string[i] != this->data[i])
            {
                result = false;
                break; //one error is enough
            }
        }
    }
    return result;
}
wString& wString::operator +=(wString& string)
{
    char* buffer = "";
    for(int i=0;i<this->length();i++) buffer += this->data[i];
    for(int i=0;i<string.length();i++) buffer += string.data[i];
    wString result = wString(buffer);
    return result;
}
wString& wString::operator +=(std::string& string)
{
    wString str1 = wString(string);
    char* buffer = "";
    for(int i=0;i<this->length();i++) buffer += this->data[i];
    for(int i=0;i<str1.length();i++) buffer += str1.data[i];
    wString result = wString(buffer);
    return result;
}
wString& wString::operator +=(char& c)
{
    char* buffer = "";
    for(int i=0;i<this->length();i++) buffer += this->data[i];
    buffer += c;
    wString result = wString(buffer);
    return result;
}

wString wString::operator +(wString& string)
{
    char* buffer = "";
    for(int i=0;i<this->length();i++) buffer += this->data[i];
    for(int i=0;i<string.length();i++) buffer += string.data[i];
    wString result = wString(buffer);
    return result;
}
wString wString::operator +(std::string& string)
{
    wString str1 = wString(string);
    char* buffer = "";
    for(int i=0;i<this->length();i++) buffer += this->data[i];
    for(int i=0;i<str1.length();i++) buffer += str1.data[i];
    wString result = wString(buffer);
    return result;
}
std::ostream& wString::operator<<(std::ostream &stream,wString &str)
{
  stream << str;
  return stream;  // return the stream
}
char wString::operator [](int& pos)
{
    if(pos < 0 || pos > this->length() -1) throw new std::exception;
    return this->data[pos];
}
std::string wString::to_std_string()
{
    std::string buffer = "";
    for(int i=0;i<this->length()-1;i++) buffer += this->data[i];
    return buffer;
}
char* wString::to_c_string()
{
    ::std::string buffer = this->to_std_string();
    char* result = (char*)buffer.c_str();
    return result;
}
wString* wString::split(const char c)
{
    wString* array = NULL; //declaration of the array, pointing to nothing
    wString string1, string2;
    int pos = this->Find(c);
    for(int i = 0;i<pos;i++) string1 += this->data[i];
    for(int i = this->data.size();i<this->length();i++) string2 += this->data[i];
    array = new wString[2];
    array[0] = string1;
    array[1] = string2;
    return array;
}
int wString::length()
{
    int len = int(sizeof(this->data));
    return len;
}
bool wString::empty()
{
    if(sizeof(this->data) == 0 || sizeof(this->data) == -1) return true;
    else return false;
}
wString& wString::swap(wString& str)
{
    wString buffer = str;
    str.data = this->data;
    return buffer;
}
void wString::Clear()
{
    this->data.clear();
}
int wString::Find(const char c)
{
    int pos = -1;
    for(int i=0;i<this->length();i++)
    {
        if(this->data[i] == c)
        {
            pos = i;
            break;
        }
    }
    return pos;
}
void wString::Print()
{
    std::string buffer = "";
    for(unsigned i=0;i<this->data.size();i++) buffer += this->data[i];
    std::cout << buffer;
}



PS: I know there are certainly parts that can be done better, but this is the first time I'm doing this, so please have some mercy :)
Was This Post Helpful? 0
  • +
  • -

#4 AKMafia001  Icon User is offline

  • </code.in.dream>

Reputation: 187
  • View blog
  • Posts: 625
  • Joined: 11-June 11

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:06 AM

Well! I might be wrong but I wanted to say that, the operator is overloaded using friend function.
Then why using the scope resolution operator ::?
std::ostream& wString::operator<<(std::ostream &stream, const wString str)

Here, wString::operator<<...

If I don't make any sense, I'm sorry!
Was This Post Helpful? 1
  • +
  • -

#5 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:24 AM

I tought that was needed since I'm declaring a operator of that class? I'll give it a shot. thanks thoug
Was This Post Helpful? 0
  • +
  • -

#6 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:25 AM

Okay the problem is in this line:
std::ostream& wString::operator<<(std::ostream &stream,wString &str)

Since this is a friend you don't need the class scope operator (wString:: ).

Also note you have several other major problems:

Quote

main.cpp||In member function ‘wString& wString::operator+=(wString&)’:|
main.cpp|124|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
main.cpp|127|warning: reference to local variable ‘result’ returned [enabled by default]|
main.cpp||In member function ‘wString& wString::operator+=(std::string&)’:|
main.cpp|133|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
main.cpp|136|warning: reference to local variable ‘result’ returned [enabled by default]|
main.cpp||In member function ‘wString& wString::operator+=(char&)’:|
main.cpp|141|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
main.cpp|144|warning: reference to local variable ‘result’ returned [enabled by default]|
main.cpp||In member function ‘wString wString::operator+(wString&)’:|
main.cpp|150|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
main.cpp||In member function ‘wString wString::operator+(std::string&)’:|
main.cpp|159|warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]|
main.cpp||In member function ‘wString& wString::swap(wString&)’:|
main.cpp|213|warning: reference to local variable ‘buffer’ returned [enabled by default]|
/usr/lib/crt1.o||In function `_start':|
/usr/src/rpm/BUILD/glibc-2.13/csu/../sysdeps/i386/elf/start.S|115|undefined reference to `main'|
||=== Build finished: 1 errors, 9 warnings ===|

Although these are warnings they should be treated as errors!

In the following snippet:
wString& wString::operator +=(wString& string)
{
   char* buffer = "";
   for(int i=0; i<this->length(); i++) buffer += this->data[i];
   for(int i=0; i<string.length(); i++) buffer += string.data[i];
   wString result = wString(buffer);
   return result;
}

When you initialize your buffer with "" you allocate enough room to hold exactly one character, the end of string character. So any attempt to access this variable past buffer[0] would be accessing this array out of bounds. Why are you using a character buffer? You are using std::strings else where why not use a std::string as your buffer?

Also you should not name your parameter string since you are also using the std::string class in this program.

Jim

This post has been edited by jimblumberg: 24 November 2012 - 07:26 AM

Was This Post Helpful? 0
  • +
  • -

#7 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:28 AM

after trying, it works now. but, since I left out the wString:: it no longer is from the wString class and gives an error when trying to cout << a wString
Was This Post Helpful? 0
  • +
  • -

#8 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:29 AM

Show how you're trying to output the wString, and the complete error message.

Jim
Was This Post Helpful? 0
  • +
  • -

#9 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:33 AM

the code:
#include <QApplication>
#include "wstring.h"
using namespace std;
/*
 *QApplication a(argc, argv);
 *return a.exec();
 */
int main(int argc, char *argv[])
{
    char* pointerTest = "hello world";
    string str = "hello world";
    wString test1 = wString(pointerTest);
    wString test2 = wString(str);
    if(test1 == test2) cout << "success" << endl;
    else cout << "failure" << endl;
    cout << test1 << endl;
}


the output:
Starting /home/Jiro/projects/QT/systemManager/release/system-manager...
success
The program has unexpectedly finished.
/home/Jiro/projects/QT/systemManager/release/system-manager exited with code 0

Was This Post Helpful? 0
  • +
  • -

#10 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 07:37 AM

Normally an exit code 0 signifies success. Have you tried returning a value from main()?

Also have you tried printing out test2 instead of test1?

Have you looked into the "warnings" I mentioned?

Edit:
Also shouldn't you be printing the "data" in your overloaded function?


Jim

This post has been edited by jimblumberg: 24 November 2012 - 07:42 AM

Was This Post Helpful? 0
  • +
  • -

#11 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 12:07 PM

I've looked into the warnings you've mentioned and reduced them to these:
../Wlib/wstring.cpp: In member function 'wString& wString::operator+=(wString&)':
../Wlib/wstring.cpp:67:13: warning: reference to local variable 'result' returned [enabled by default]
../Wlib/wstring.cpp: In member function 'wString& wString::operator+=(std::string&)':
../Wlib/wstring.cpp:76:13: warning: reference to local variable 'result' returned [enabled by default]
../Wlib/wstring.cpp: In member function 'wString& wString::operator+=(char&)':
../Wlib/wstring.cpp:84:13: warning: reference to local variable 'result' returned [enabled by default]
../Wlib/wstring.cpp: In member function 'wString& wString::swap(wString&)':
../Wlib/wstring.cpp:151:13: warning: reference to local variable 'buffer' returned [enabled by default]


and for the code, I've compiled successfully at the moment of writing with this code:
header:
friend std::ostream &operator<<(std::ostream &os, const wString &str);


source file:
std::ostream &operator<<(std::ostream &os, const wString &str)
{
    os << str;
    return os;  // return the stream
}


my thanks for spending time helping me out and my apologies for the late reply
Was This Post Helpful? 0
  • +
  • -

#12 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 24 November 2012 - 12:45 PM

In your overloaded operator<< you need to print the "data" not the instance. Try printing your vector by using a loop.

For the rest of your warnings please post the current code for the mentioned functions.

Jim
Was This Post Helpful? 0
  • +
  • -

#13 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 27 November 2012 - 01:35 AM

after an update,
source:
#include "wstring.h"
namespace wDataType
{
    basic_wString::basic_wString()
    {
    }
    basic_wString::basic_wString(char *c)
    {
        std::string str = std::string(c); //std::string is easer to work trough
        for(unsigned i=0;i<str.length();i++) this->data.push_back(str[i]);
    }
    basic_wString::basic_wString(const std::string &str)
    {
        for(unsigned i=0;i<str.length();i++) this->data.push_back(str[i]);
    }
    basic_wString::basic_wString(char c)
    {
        this->data.push_back(c);
    }

    basic_wString::~basic_wString()
    {
        this->data.clear();
    }
    bool basic_wString::operator ==(basic_wString& string)
    {
        if(this->data == string.data) return true;
        else return false;
    }
    bool basic_wString::operator ==(std::string& string)
    {
        bool result = true;
        if(string.length() != this->data.size())result = false;
        if(result != false)
        {
            for(unsigned i=0;i<this->data.size();i++)
            {
                if(string[i] != this->data[i])
                {
                    result = false;
                    break; //one error is enough
                }
            }
        }
        return result;
    }
    bool basic_wString::operator ==(char* string)
    {
        bool result = true;
        if(sizeof(string) != this->data.size())result = false;
        if(result != false)
        {
            for(unsigned i=0;i<this->data.size();i++)
            {
                if(string[i] != this->data[i])
                {
                    result = false;
                    break; //one error is enough
                }
            }
        }
        return result;
    }
    basic_wString& basic_wString::operator +=(basic_wString& string)
    {
        std::string buffer = "";
        for(int i=0;i<this->length();i++) buffer += this->data[i];
        for(int i=0;i<string.length();i++) buffer += string.data[i];
        basic_wString result = basic_wString(buffer);
        return result;
    }
    basic_wString& basic_wString::operator +=(std::string& string)
    {
        basic_wString str1 = basic_wString(string);
        std::string buffer = "";
        for(int i=0;i<this->length();i++) buffer += this->data[i];
        for(int i=0;i<str1.length();i++) buffer += str1.data[i];
        basic_wString result = basic_wString(buffer);
        return result;
    }
    basic_wString& basic_wString::operator +=(char& c)
    {
        std::string buffer = "";
        for(int i=0;i<this->length();i++) buffer += this->data[i];
        buffer += c;
        basic_wString result = basic_wString(buffer);
        return result;
    }

    basic_wString basic_wString::operator +(basic_wString& string)
    {
        std::string buffer = "";
        for(int i=0;i<this->length();i++) buffer += this->data[i];
        for(int i=0;i<string.length();i++) buffer += string.data[i];
        basic_wString result = basic_wString(buffer);
        return result;
    }
    basic_wString basic_wString::operator +(std::string& string)
    {
        basic_wString str1 = basic_wString(string);
        std::string buffer = "";
        for(int i=0;i<this->length();i++) buffer += this->data[i];
        for(int i=0;i<str1.length();i++) buffer += str1.data[i];
        basic_wString result = basic_wString(buffer);
        return result;
    }
    std::ostream &operator<<(std::ostream &os, const basic_wString &str)
    {
        basic_wString buffer = str;
        os << buffer.to_std_string();
        return os;  // return the stream
    }
    char basic_wString::operator [](int& pos)
    {
        if(pos < 0 || pos > this->length() -1) throw new std::exception;
        return this->data[pos];
    }
    std::string basic_wString::to_std_string()
    {
        std::string buffer = "";
        for(int i=0;i<this->length()-1;i++) buffer += this->data[i];
        return buffer;
    }
    char* basic_wString::to_c_string()
    {
        ::std::string buffer = this->to_std_string();
        char* result = (char*)buffer.c_str();
        return result;
    }
    basic_wString* basic_wString::split(const char c)
    {
        basic_wString* array = NULL; //declaration of the array, pointing to nothing
        basic_wString string1, string2;
        int pos = this->Find(c);
        for(int i = 0;i<pos;i++) string1 += this->data[i];
        for(int i = this->data.size();i<this->length();i++) string2 += this->data[i];
        array = new basic_wString[2];
        array[0] = string1;
        array[1] = string2;
        return array;
    }
    int basic_wString::length()
    {
        int len = int(sizeof(this->data));
        return len;
    }
    bool basic_wString::empty()
    {
        if(this->data.size() == 0 || this->data.size() == -1) return true;
        else return false;
    }
    basic_wString& basic_wString::swap(basic_wString &str)
    {
        basic_wString buffer = str;
        str.data = this->data;
        return buffer;
    }
    void basic_wString::Clear()
    {
        this->data.clear();
    }
    int basic_wString::Find(const char c)
    {
        int pos = -1;
        for(int i=0;i<this->length();i++)
        {
            if(this->data[i] == c)
            {
                pos = i;
                break;
            }
        }
        return pos;
    }
    void basic_wString::Print()
    {
        std::string buffer = "";
        for(unsigned i=0;i<this->data.size();i++) buffer += this->data[i];
        std::cout << buffer;
    }

} //wDatatype




and the header:
#ifndef WSTRING_H
#define WSTRING_H

#include <iostream>
#include <vector>

namespace wDataType
{
    class basic_wString
    {
    protected:
        //variables
        std::vector<char> data;
        //end of vars
    public:
        //begin constructors

        basic_wString();
        basic_wString(char *c);
        basic_wString(const std::string& str);
        basic_wString(char c);
        ~basic_wString(void);

        //end constructors

        //begin operators

        bool operator ==(basic_wString& string);
        bool operator ==(std::string& string);
        bool operator ==(char* string);
        basic_wString& operator +=(basic_wString& string);
        basic_wString& operator +=(std::string& string);
        basic_wString& operator +=(char& c);
        basic_wString operator +(basic_wString& string);
        basic_wString operator +(std::string& string);
        friend std::ostream &operator<<(std::ostream &os, const basic_wString &str);
        char operator [](int& pos);

        //end of operators
        //functions

        std::string to_std_string(); //verander je wString in een normale C++ string
        char* to_c_string(); //verander je wString in een C-stijl string
        basic_wString* split(const char c); //splits hem in meerdere Wstrings (*pointer to the array)
        int length(); //verkrijg de lengte van de wString
        bool empty(); //kijk na of er iets in de string zit
        basic_wString& swap(basic_wString& str); //verwissel de data van twee wStringen
        void Clear(); //maak de hele string leeg
        int Find(const char c);
        void Print();
        //end of functions
    };
    typedef basic_wString wString;
}

#endif // WSTRING_H



Was This Post Helpful? 0
  • +
  • -

#14 jimblumberg  Icon User is offline

  • member icon


Reputation: 4278
  • View blog
  • Posts: 13,434
  • Joined: 25-December 09

Re: trouble overloading '<<' operator for custom string cl

Posted 27 November 2012 - 07:11 AM

Do you have any questions, problems with the code you provided?

Your code can be simplified in many places by getting rid of the "this->" when accessing the class member functions/variables.

See the following example:
 
void basic_wString::Print()
{
   std::string buffer = "";
   for(unsigned i=0; i<this->data.size(); i++)
      buffer += this->data[i];
   std::cout << buffer;
}


You can simplify things quite a bit. First you don't need to use the "this->" when referring to the data members. And you don't need the variable buffer, just print out the characters of your vector. Also when you want to construct an empty string you don't need the assignment operator, just use the constructor without any arguments.

 
void basic_wString::Print()
{
   for(size_t i=0; i < data.size(); i++)
      std::cout << data[i];
}



To construct an std::string use: std::string temp;.

Jim
Was This Post Helpful? 0
  • +
  • -

#15 Jiro_  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 66
  • Joined: 27-August 12

Re: trouble overloading '<<' operator for custom string cl

Posted 01 December 2012 - 03:46 PM

I dont really have further questions, i am gratefull you took time answering mine thoug. Thanks a lot!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1