user2710184
user2710184

Reputation: 347

Non-Ivalue in assignment error

I'm getting the above error message twice during compile time. Everything else works fine i.e no other compile time errors. This is a simple binary tree program and the function where the errors are coming from is a swap or mirror function meant to simply to swap all subtrees. Here is the function

template <class dataType>
void swapSubTrees ( BinaryTree <dataType> * bt )
{
    if(bt == NULL)
    {
        //do nothing  
    }
    else
    {  
        swapSubTrees(bt->left());
        swapSubTrees(bt->right());
        BinaryTree <int> *temp;
        temp = bt->left();
        bt->left() = bt->right();
        bt->right() = temp;
   }
}

and here is my function call in the main (this is where I get the two non-lvalue errors

swapSubTrees (b1);

b1 is an object instantiated from class BinaryTree and it is at the top of my tree. There are corresponding objects b2,b3,b4 and b5 which are other nodes of the tree, obviously from code that I have left out. Anyway I cannot seem to find where I went wrong, what could it be? Any help would be great thanks! and the left function looks like

Template <class dataType>
BinaryTree <dataType> * BinaryTree<dataType> :: left()
{
    return leftTree;
}

Upvotes: 1

Views: 167

Answers (4)

John3136
John3136

Reputation: 29266

I'm guessing the lines that give the errors are:

bt->left() = bt->right();
bt->right() = temp;

?

You can't use a function call like that as the left hand side of an expression.


Add this method to the BinaryTree template class:

template<class dataType>
void BinaryTree<dataType>::swapChildren()
{
    BinaryTree *tmp = leftTree;
    leftTree = rightTree;
    rightTree = tmp;

    if (leftTree)
        leftTree->swapChildren();
    if (rightTree)
        rightTree->swapChildren();
}

Then change your free-function to simply be:

template <class dataType>
void swapSubTrees ( BinaryTree <dataType> * bt )
{
    if(bt != NULL)
        bt->swapChildren();
}

Upvotes: 4

Agentlien
Agentlien

Reputation: 5116

The problem here is that you are trying to assign a value to an rvalue.

Essentially, the cause is that the value returned by left and right is a temporary object. You're returning a copy of the pointer, and this copy cannot be assigned to.

The way to get this to compile is to change the left and right functions to return a reference to your pointer, which can be assigned to. This is done as follows:

Template <class dataType>
BinaryTree <dataType>*& BinaryTree<dataType> :: left()
{
    return leftTree;
}

(And similarly for right)

Note the ampersand (&) after the asterisk (*). This means the returned value is a reference. This is called returning by reference, rather than returning by value.

Now, this would cause the code to compile. But you really should ask yourself if this is what you want. Do you want someone from outside to be allowed to change what leftTree points to inside the BinaryTree?

A better option would likely be to add a setter function for these two, and call these instead.

Upvotes: 0

benjymous
benjymous

Reputation: 2122

Add

void setLeft( BinaryTree <dataType> * other );

and

void setRight( BinaryTree <dataType> * other );

To your BinaryTree class, assuming they don't already exist (I'll leave the implementation of those to you!)

then change the erroring lines to

bt->setLeft( bt->right() );
bt->setRight( temp );

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310920

If you will rewrite your functions left() and right() as returning reference to pointer then there will not be a problem.:)

Upvotes: -1

Related Questions