У меня есть следующий код:
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;
}
Проблема с этим кодом заключается в том, что у меня есть много вариантов конструкторов для игры в реальности, и я хочу избежать, чтобы удалить все остальные, чтобы я хотел что-то вроде
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 &) и т.д....
Это возможно? (Конечно, класс Ruleset должен объявить конструкторы перемещения сейчас). Также укажите, когда у вас есть лучший подход к проблеме, который помогает мне эффективно кодировать этот класс.
Если вы хотите принимать только lvalues, вы можете просто написать конструктор, который делает это:
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; }
std::forward(r)
никогда не является действительным, вы должны предоставить список аргументов шаблона. Может быть, вы просто хотитеGame(RuleSet r) : rules(std::move(r)) { }
которая будет делать копию и перемещение, если передано lvalue, или два хода, если передано rvalue.