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 MVariable
{
public:
virtual void setValue(T value) { // -- (A)
m_state = value;
// (... more things.)
}
virtual void setValue(T&& value) { // -- (B)
m_state = value;
// (... more things.)
}
protected:
T m_state;
};
template <class T>
class MOutput : public MLinkedOVariable, public MState<T>
{
public:
void setValue(T value) override { // -- (C)
MState<T>::setValue(static_cast<T&&>(value));
// (... even more things.)
}
void setValue(T&& value) override { // -- (D)
MState<T>::setValue(static_cast<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).
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?
Consulted references
- https://www.codesynthesis.com/~boris/blog/2012/06/26/efficient-argument-passing-cxx11-part2/
- https://stackoverflow.com/a/31551595/1876268
- https://stackoverflow.com/a/3582313/1876268
- https://stackoverflow.com/a/40350289/1876268
- https://stackoverflow.com/a/5465371/1876268
Aucun commentaire:
Enregistrer un commentaire