我有一个与参考转发有关的问题,对此我只是略有熟悉。在陈述我的问题之前,我想说的是,我已经阅读了与该语言功能相关的几页,它们使我感到困惑,而不是让我陷入困境。参考的参考文献是:[1-5],我发现其中一些自相矛盾或不完全理解。意识到这个问题可以被视为重复的事实,我还是将其发布,因为我找不到一个可以将这三个因素结合在一起的案例:
我有两个用于表示模型变量的类。通用的是MState<T>
,我将其作为模板,因为我希望它在其中包装任何可能的类型。它更像是我为与该问题无关的目的而创建的类型的包装。然后,我有了MOutput<T>
,它实际上扩展了MState<T>
,并表示用户定义模型的外部可见变量。
它们都有一个名为setValue
的成员函数,该函数允许...设置它们的值。我知道实现操作符语义会很好,但是现在我正在处理这个问题:
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.)
}
};
我认为我需要(A)允许l值成为对MState::setValue
的调用中的有效参数。实际上,如果我删除它,编译器会抱怨它无法将l值转换为r值引用(我用[{4]理解。)但是,我想避免不必要的资源分配和复制,尤其是与临时人员打交道时(例如ms.setValue(MyClass())
。)因此是(B)。
同样,(C)是必需的,因为除了MOutput
实现的功能之外,我还需要MState
做更多的事情。对于上述相同的动机,我也想要(D)。
[3]促使在(C)和(D)中使用std::forward<T>(value)
。
当我尝试编译代码时,GCC抱怨重载的函数签名在两个类和许多情况下都模棱两可。我想我不明白为什么或如何解决这个问题。 T&&
在这里是通用参考吗?如果是这样,这些人不应该接受任何类型的参数类型吗?
GCC无法编译(C)和(D)的第MState<T>::setValue(std::forward<T>(value));
行。如果我将其注释掉,则在以下情况下会出现相同的歧义错误:
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.
答案 0 :(得分:1)
我相信在这种情况下,它无法确定是复制T还是通过右值引用将其传递,从而造成歧义。尝试对第一个函数采用对T的const引用。
std :: forward也适用于进行通用引用(在推断的上下文中为右值引用)时,我认为它不适用于此处。
答案 1 :(得分:1)
我只需要简单的void setValue(const T& value)
(当您的getter进行复制时,甚至更多)。
但是,如果您既想要l值引用又要r值引用,它将类似于:
template <class T>
class MState
{
public:
virtual void setValue(const T& value) {
m_state = value;
MoreStuff()
}
virtual void setValue(T&& value) {
m_state = std::move(value);
MoreStuff()
}
const T& getValue() const { return m_state; }
private:
void MoreStuff();
protected:
T m_state;
};
template <class T>
class MOutput : public MState<T>
{
public:
void setValue(const T& value) override {
MState<T>::setValue(value);
MoreThings();
}
void setValue(T&& value) override {
MState<T>::setValue(std::move(value));
MoreThings();
}
private:
void MoreThings();
};
这里的T &&是通用参考吗?
作为状态,在评论中,不是,T
由类固定。