I have a problem related to reference forwarding, to which I am only slightly familiar with. Before stating my question, I want to say that I've read a few pages related to this language feature and they kind of confused me rather than shedding light into my problem. The consulted references are: [1-5], some of which I find contradictory or don't fully understand. Aware of the fact that this question could be considered a duplicate, I am posting it anyways because I couldn't find a case that would combine these three factors:
- Overloaded functions with r-value references.
- Templated classes (not functions).
- Override of overloaded functions where the parent class' function is called in the overrides.
Problem scenario
I have two classes that I use to represent a variable of a model. The generic one is MState<T> and I template it because I want it to wrap any possible type inside. It's more like a wrapper to a type that I have created for a purpose which is irrelevant to this question. Then, I have MOutput<T>, which essentially extends MState<T> and represents an externally visible variable of a user-defined model.
They both have a member function called setValue which allows to, well... set their value. I know it would be nices to implement operator semantics, but for now I'm dealing with this:
template <class T>
class MState
{
public:
    virtual void setValue(T value) {      // -- (A)
        m_state = value;
        // (... more things.)
    }
    virtual void setValue(T&& value) {    // -- (B)
        m_state = value;
        // (... more things.)
    }
    T getValue(void) { return m_state; }
protected:
    T m_state;
};
template <class T>
class MOutput : public MState<T>
{
public:
    void setValue(T value) override {                     // -- (C)
        MState<T>::setValue(std::forward<T>(value));
        // (... even more things.)
    }
    void setValue(T&& value) override {                   // -- (D)
        MState<T>::setValue(std::forward<T>(value));
        // (... even more things.)
    }
};
I think I need (A) to allow for l-values to be valid arguments in calls to MState::setValue. Actually, if I remove it the compiler complains that it cannot convert an l-value to an r-value reference (which I understood with [4].) However, I want to avoid unnecessary resource allocations and copies, especially when dealing with temporaries (e.g. ms.setValue(MyClass()).) Hence (B).
Likewise, (C) is necessary because I need MOutput's to do a few things more, in addition to the ones MState implements. For the same motivation above, I also want (D).
The use of std::forward<T>(value) in (C) and (D) is motivated by [3].
Question
When I try to compile my code, GCC complains about the overloaded function signature to be ambiguous in both classes and a number of cases. I think I don't understand why, or how to solve the issue. Is T&& here a universal reference? If so, shouldn't these accept any kind of argument type?
Use cases
GCC fails to compile the line MState<T>::setValue(std::forward<T>(value)); of both (C) and (D). If I comment them out, I get the same ambiguity error in these cases:
bool function(int a) { return a >= 1; }
MOutput<bool> vo0, vo1, vo2;
vo1.setValue(true);                                // Error.
vo2.setValue(false);                               // Error.
vo0.setValue(!(vo1.getValue() & vo2.getValue()));  // Error.
MOutput<int> vo3;
vo3.setValue(432);                                 // Error.
 
     
     
    