Error; The left operand must be L-value

1

I have to build a doubly linked list, but I was presented with an error that I can not solve:

Node class
It is important to note that this class makes use of template to accept any format.

#ifndef nodo_h
#define nodo_h
#include <iostream>
using namespace std;

template<class type>
class nodo
{
private:
    type element;
    nodo *next, *previous;
public:
    void SetElement(type element);
    void ShowElement();
    type GetElement();
    nodo<type>* GetNext();
    nodo<type>* GetPrevious();
    nodo<type>();
    ~nodo<type>();

};

Class list8
The problems are presented in the procedures SetFirst and SetLast
I forgot to say that this list must also use template to be able to send variables from main , so first access to lista8 where there is a list not yet defined of the class nodo

#ifndef lista8_h
#define lista8_h
#include "nodo.h"

template<class type>
class lista8
{
private:
    nodo<type> *first, *last;
public:
    void SetFirst(type NewElement); //<-error
    void SetLast(type NewElement); //<-error
    int ClearFirst();
    int ClearLast();
    void ShowList(nodo<type> *list);
    nodo<type>* GetFirst();
    nodo<type>* GetLast();
    lista8<type>();
    ~lista8<type>();
};

Here is the code of SetFirst and SetLast , including where the error is,
the error that visual studio shows me is what it says in the title .
(being more specific, it says: C2106 '=': the operand must be value L)
Where it says 'error that I expected' is where I imagined that this error would also appear, but interestingly, it does not tell me that it is incorrect .

template<class type>
void lista8<type>::SetFirst(type NewElement)
{
    if (first == NULL)
    {
        first = new nodo<type>; //<--error que esperaba
        last = first;
    }
    else
    {
        first->GetPrevious() = new nodo<type>; //<--error
        first->GetPrevious()->GetNext() = first; //<--error
        first = first->GetPrevious();
    }
    first->SetElement(NewElement);
}

template<class type>
void lista8<type>::SetLast(type NewElement)
{
    if (last == NULL)
    {
        last = new nodo<type>; //<--error que esperaba
        first = last;
    }
    else
    {
        last->GetNext() = new nodo<type>; //<--error
        last->GetNext()->GetPrevious() = last; //<--error
        last = last->GetNext();
    }
    last->SetElement(NewElement);
}
    
asked by Max 15.08.2018 в 04:30
source

2 answers

1

I recommend, as an initial reading, this other question .

If I have this:

struct POO
{
  POO() : a(0)
  { }

  int func()
  { return a; }

  int a;
};

int main()
{
  POO p;
  p.func() = 10;
  std::cout << p.a;
}

Do you think it will work?

Obviously it should not, at least not as expected, seeing the intent of the code. func returns a copy of a , then the assignment p.func() = 10 can hardly modify the value of a .

Well, with the pointers the same thing happens. A pointer is a variable whose main characteristic is that it stores a memory address. When you copies a pointer:

int a;
int* ptr = &a;
int* ptr2 = ptr; // <<---

What happens is that the memory address is copied to the new pointer. Thus, both pointers have the same memory address stored and, therefore, changes in said memory will be visible for both pointers. The detail here is that we have copied the memory address , if later we make that one of the two pointers points to another different region the other pointer will not find out:

int a = 1, b = 2;
int* ptr1 = &a;
int* ptr2 = ptr1;
std::cout << *ptr1 << *ptr2 << '\n'; // Imprime 11
ptr2 = &b;
std::cout << *ptr1 << *ptr2 << '\n'; // Imprime 12

Well, what are you pretending in this line?

first->GetPrevious() = new nodo<type>;

The internal pointer previous is updated. However GetPrevious returns a copy of that pointer and, as we have seen, from a copy it is impossible to modify the original element.

The cleanest thing is that you add a SetPrevious that allows modifying the pointer:

template<class type>
class nodo
{
private:
    type element;
    nodo *next, *previous;
public:
    void SetElement(type element);
    void ShowElement();
    type GetElement();
    nodo* GetNext();
    nodo* GetPrevious();

    void SetPrevious(nodo*);
};
    
answered by 16.08.2018 / 09:01
source
0

@Max the solution you have been proposed does not make magic, you are simply returning a reference to the pointer ... it is as if the function returned a double pointer (similar). This solution is used a lot by the STL ... but only with constant references, that is, you could not modify its value unless you use techniques that are not recommended at all

    
answered by 17.08.2018 в 06:42