3

Currently I'm trying to rewrite the += operator for a class I wrote called mystring:

MyString& operator+=(MyString& s1, const MyString& s2)
{

    int newStringLength = s1.length + s2.length;
    char* newStorage = new char[newStringLength +  1];

    strcpy(newStorage, s1.data);

    strcpy(newStorage + s1.length, s2.data);
    delete[] s1.data;

    s1.length = newStringLength;
    s1.data = newStorage;

    return s1;

}

MyString operator+(const MyString& s1, const MyString& s2)
{

    MyString temp;
    delete[] temp.data;

    temp.length = s1.length;
    temp.data = new char[temp.length+1];

    strcpy(temp.data, s1.data);
    temp+=s2;

    return temp;

}

Where length is the length of the string and data is a string stored in char * format.

The program works fine when I try to do something like:

MyString test1 = "hi";
MyString test2 = "to"; 

test1 += test2;

But does not work when I try something like:

   MyString test;
    MyString test1 = "hi";
    MyString test2 = "to"; 

    test += test2 + test1
          += "you";

Basically when I start mixing += and + in an alternating way it doesn't work. Here is the error at compilation:

testoutput.cpp:26: error: no match for ‘operator+=’ in ‘operator+(const MyString&, const MyString&)(((const MyString&)((const MyString*)(& test1)))) += "you"’
mystring.h:45: note: candidates are: MyString& operator+=(MyString&, const MyString&)

Does anyone have any idea how I can change my code in order to achieve this functionality?

KWJ2104
  • 1,959
  • 6
  • 38
  • 53
  • what is `s1.data` initialized to in the default constructor (which is what you're calling with `MyString test;`? – matthias Dec 08 '11 at 02:42
  • data = new char[1]; data[0] = '\0'; length = 0; – KWJ2104 Dec 08 '11 at 02:44
  • Can you post the full source for the MyString class? – Ternary Dec 08 '11 at 02:45
  • 1
    This functionality doesn't make ant sense. What do you want multiple += to mean in the same statement? That's changing the semantics of the operator. – danca Dec 08 '11 at 02:46
  • Can't operator + just be something like "return s1 + s2" ? – hookenz Dec 08 '11 at 02:48
  • Add print statements to the functions to see what is happening in what order. Also, what is the contents of each of the three variables after that statement is executed? – Seth Carnegie Dec 08 '11 at 02:50
  • 1
    If ask about a problem you should really include a description of that problem in your question. "Does not work" is the worst possible problem description. If you don't say what goes wrong, how do you expect anybody to be able to help? – sth Dec 08 '11 at 02:56
  • @MattH I presume you mean `operator+=`. Yes, there's a very good case for it being implemented in terms of `operator+`, and he probably should--though he would need to remove the call to `operator+=` from within `operator+`. – matthias Dec 08 '11 at 02:58

2 Answers2

3

It doesn't make sense to mix + and += in such a way. I'm not really sure what your intended behavior is, but if you want the nested += to apply to test1, you'll have to use parenthesis:

test += test2 + (test1 += "you");

This is not a problem with your assignment operator, but with operator precedence in the language. If you would replace MyString with int you would run into the same problems.

The precedence and associativity of the + and += operators causes the expression without parenthesis to be interpreted like this:

test += ((test2 + test1) += "you");

This tries to assign to test2 + test1, but that's not possible (you can only assign to variables). This operator precedence cannot be changed and without parenthesis the expression will always be interpreted this way.

sth
  • 222,467
  • 53
  • 283
  • 367
  • Can you expound on how operator precedence makes it that I can't compile without the parenthesis? I tried your method and it indeed does make it work. Is there a way to get it to work without hte parenthesis? – KWJ2104 Dec 08 '11 at 02:57
  • Also in response to your comment sorry about not being more specific on the OP, I edited in the error message on compilation in my post a while ago. – KWJ2104 Dec 08 '11 at 02:58
0

Your mistake is here:

test += test2 + test1 += "you";

The program will create temporary object from 'test2 + test1' and will call operator+=() for it. The problem is, there are 2 operator += calls in one expression and it is undefined which one will be called first. So the result of operator+=(TemporaryObject,MyString("you")) may be lost;

To prevent this you should declare operator+ like this:

const MyString operator+(const MyString& s1, const MyString& s2)

If you do this the compiler will be able to signal an error if it stumbles upon such expressions with unpredictable result;

Edit:

Now that we have the compiler output, i see that the compiler is smart enough to see that the object created from operator+() is temporary. So, you just have to make 2 expressions instead of 1:

test += test2 + test1;
test += "you";

But still i suggest to return const object from your operator+();

Pavel Zhuravlev
  • 2,691
  • 1
  • 18
  • 17
  • But aren't operators just called in the order they appear if they are of the same precedence? For example why would this not mess up if test1 + test2 + test3 or something is called, doesn't it have to judge which + should be called first? I might just be really confused. Also I tried adding const but my code still does not compile and gives the same error. – KWJ2104 Dec 08 '11 at 03:07
  • According to the Stroustrup's 'The C++ Programming Language' "The order of evaluation of subexpressions within an expression is undefined". Can't make the reference to the standard – Pavel Zhuravlev Dec 08 '11 at 03:12
  • Small addition: you should not mess up precedence, associativity and order of evaluation. A good explanation is given here: [link](http://stackoverflow.com/questions/5473107/operator-precedence-vs-order-of-evaluation) – Pavel Zhuravlev Dec 08 '11 at 04:03