【问题标题】:How to call std::forward when type is known已知类型时如何调用 std::forward
【发布时间】:2015-01-08 04:41:40
【问题描述】:

我有以下代码:

class Game {
private:
    const Ruleset& rules;
public:
    Game(const Ruleset&);
}

public class Ruleset {
public:
    virtual ~Ruleset();
    virtual bool isMoveValid(Move&) const = 0;
}

现在以下初始化程序可以正常工作:

Game::Game(const Ruleset& r) : rules(r) {}

但我刚刚发现这并不能保护我免受对临时对象的悬空引用。我想到了以下解决方案:

class Game {
private:
    const Ruleset& rules;
public:
    Game(const Ruleset&);
    Game(const Ruleset&&) = delete;
}

这段代码的问题在于,我在现实中为 Game 有很多不同的构造函数,我想避免专门删除其他所有构造函数,所以我想要类似的东西

class Game {
private:
    const Ruleset rules;
public:
    Game(const Ruleset&&);
}

Game::Game(const Ruleset& r) : rules(forward(r)) {}

可能带有更多复制/移动的参数。假设我有一个带有 4 个参数的构造函数:

Constructor(type1&, type2&, type3&, type4&).

然后我想尽可能使用 move-constructor,但我不想编写 Constructor(type1&&, type2&, type3&, type4&) 等的每个变体...

这可能吗? (当然现在规则集类必须声明移动构造函数)。还请指出您何时有更好的方法来帮助我有效地编写此类代码。

【问题讨论】:

  • “我想要类似”代码中的构造函数签名不匹配,不清楚您希望它做什么
  • std::forward(r) 永远无效,您必须提供模板参数列表。也许您只想要Game(RuleSet r) : rules(std::move(r)) { },如果传递一个左值,它将执行复制和移动,或者如果传递一个右值,则执行两个移动。
  • 谢谢乔纳森,我想多了,std::move 在这种情况下应该可以正常工作吗?它是如何工作的,我认为 move 在每种情况下都会将其转换为右值,这如何调用复制构造函数?
  • 可以调用复制构造函数来初始化r,然后rules总是被移动构造函数初始化。
  • 等一下,您可以按值存储规则集吗?这改变了问题。

标签: c++ c++11 reference constants move-semantics


【解决方案1】:

如果你只想接受左值,你可以写一个构造函数来做到这一点:

Game(RuleSet& r)
: rules(r)
{ }

这样你就不能轻易地通过临时的,你仍然可以通过const& 来传递。

您还可以通过通用 ref 获取每个参数并逐个转发每个参数。这也将隐藏const 方面并强制您的rules 成员成为const RulesSet* 而不是引用:

template <typename Arg1, typename Arg2>
Game(Arg1&& a1, Arg2&& a2)
{
    initRulesSet(std::forward<Arg1>(a1));
    initSomethingElse(std::forward<Arg2>(a2));
}

void initRulesSet(RulesSet&& ) = delete;
void initRulesSet(const RulesSet& rs) { rules = &rs; }

【讨论】:

  • 这不会给用户带来一些安全隐患吗?他们不能相信 RuleSet 现在只使用 const,不是吗?
  • @WorldSEnder 是的。但是您实际上只有三个选择:(1)您可以编写 2^N 个构造函数(2)您可以编写仅左值构造函数(3)您可以编写通用引用构造函数,分别转发每个参数,这仍然有点隐藏常量部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
  • 2015-10-13
  • 1970-01-01
  • 2011-11-07
  • 2015-09-24
  • 2016-07-08
相关资源
最近更新 更多