-1

I have a class called CircuitProfiler that has a public member function switchState. Below is the code for it:

void CircuitProfiler::switchState(int index)
{
    if (profilingNode)
    {
        switch (index)
        {
        case 0:
            node->getVoltage().isKnown = !node->getVoltage().isKnown;
            break;
        }
    }
}

The code I am having trouble with is the line:

node->getVoltage().isKnown = !node->getVoltage().isKnown;

I am getting error that says "expression must be a modifiable lvalue". There is a red line under node.

node is a pointer to an instance of a Node class that I created. node a private data member of CircuitProfiler. It is declared in CircuitProfiler as Node* node;

Node has a private data member called voltage, and getVoltage is a public member function of Node that simply returns voltage. voltage is declared in Node as VariableValue<float> voltage; and the code for getVoltage is:

VariableValue<float> Node::getVoltage()
{
    return voltage;
}

voltage is an instance of a simple struct called VariableValue, the code for which is below.

template <class T>
struct VariableValue {
    T value;
    bool isKnown;
};

So why am I getting the error "expression must be a modifiable value"? Let me know if I need to provide any more information.

  • 2
    you'd likely want `VariableValue& Node::getVoltage()`, i.e., return by reference. Otherwise you'd be modifying a temporary in the `=` call. – lorro Aug 04 '22 at 22:21
  • 1
    Read the error more carefully, you should find it say "modifiable lvalue", not "modifiable value" – M.M Aug 04 '22 at 22:45
  • `GetVoltage()` returns by value so it returns an rvalue (loosely, a value that is on the right of an assignment expression). Among other things that means the returned value will cease to exist at the end of the current statement, and modifications to it are meaningless. C++, by design, treats such deeds as a diagnosable error. If you want to modify the underlying `voltage` object that it returns, change the function so it returns a reference, not by value. – Peter Aug 05 '22 at 01:49

1 Answers1

1

You are essentially saying (MCVE):

struct S { int i; }; // S as VariableValue<float>
 
S f() { return S{}; } // f as getVoltage
 
f().i =  1; // i as isKnown

You return a temporary in getVoltage(), which does not bind to an lvalue argument of operator=().

Likely you wanted to return voltage by reference in getVoltage(), if you wanted to use it this way, i.e.,

VariableValue<float>& Node::getVoltage()
{
    return voltage;
}

You might also define a const version of it.

lorro
  • 10,687
  • 23
  • 36
  • 1
    Minor nitpick: since the operands are both built-in type, `=` here is the built-in assignment operator, it is not a function nor an overloaded operator. The built-in assignment operator requires a modifiable lvalue as left operand; `operator=()` does not have such a restriction – M.M Aug 04 '22 at 22:48
  • Thank you. Your exact solution alone was not enough, but I solved my issue by also modifying the switchState function such that it uses an intermediate VariableValue instance. – Ryan Huynh Aug 05 '22 at 03:29