Как вызвать std :: forward, когда тип известен

0

У меня есть следующий код:

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 должен объявить конструкторы перемещения сейчас). Также укажите, когда у вас есть лучший подход к проблеме, который помогает мне эффективно кодировать этот класс.

  • 0
    Сигнатуры конструктора в вашем коде "Я хочу что-то подобное" не совпадают, и неясно, на что вы надеетесь
  • 1
    std::forward(r) никогда не является действительным, вы должны предоставить список аргументов шаблона. Может быть, вы просто хотите Game(RuleSet r) : rules(std::move(r)) { } которая будет делать копию и перемещение, если передано lvalue, или два хода, если передано rvalue.
Показать ещё 3 комментария
Теги:
c++11
reference
const
move-semantics

1 ответ

1
Лучший ответ

Если вы хотите принимать только 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; }
  • 0
    Разве это не лишает пользователя безопасности? Они не могут поверить, что RuleSet используется const только сейчас, не так ли?
  • 0
    @WorldSEnder Да. Но на самом деле у вас есть только три варианта: (1) Вы можете написать 2 ^ N конструкторов (2) Вы можете написать конструкторы только для lvalue (3) Вы можете написать конструкторы universal-ref, которые передают каждый аргумент индивидуально, что по-прежнему скрывает постоянная часть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню