Как я могу собрать init структуру, которая наследуется от виртуального типа? - PullRequest
0 голосов
/ 07 марта 2020

Согласно [dcl.init.aggr] Я не могу агрегировать тип init, если он имеет (среди прочего) виртуальные функции, включая наследование от типа с виртуальным деструктором. Тем не менее, я хотел бы избежать написания тонны шаблонных конструкторов.

MWE:

struct Base {
  virtual ~Base() {}
};

struct Derived : Base {
  int i;
};

int main() {
  Derived d1{42}; // not allowed in this fashion
  Derived d2{{},42}; // also not allowed
}

В моих настройках у меня есть много типов, таких как Derived, и они все простые структуры с несколькими членами (не обязательно тривиальными / pod) , за исключением , потому что они должны наследовать от Base.

Есть ли способ избежать необходимости писать Derived(int i) : Base(), i(i) {} конструкторы для всех из них?

1 Ответ

0 голосов
/ 07 марта 2020

Единственное решение, о котором я мог подумать, - это использовать тот факт, что структура без наследования, указанного выше, с радостью выдаст инициализатор агрегата по умолчанию. Поэтому я сочиняю эту структуру вместе с шаблонным типом оболочки.

template <typename T>
struct BaseWrapper : Base, T {
  BaseWrapper(T data) : Node(), T(data) {}
  BaseWrapper() = delete;
  BaseWrapper(BaseWrapper const&) = default;
  BaseWrapper(BaseWrapper&&) = default;
  BaseWrapper& operator=(BaseWrapper const&) = default;
  BaseWrapper& operator=(BaseWrapper&&) = default;
  static T const& cast(Base const& b) {
    return static_cast<T const&>(static_cast<BaseWrapper<T> const&>(b));
  }
  static T& cast(Base& b) {
    return static_cast<T&>(static_cast<BaseWrapper<T>&>(b));
  }
};

И так как я использую типы Derived в качестве общих указателей, небольшая вспомогательная функция:

template <typename T, typename... Args>
inline std::shared_ptr<BaseWrapper<T>> make_bw(Args&&... args) {
  return std::make_shared<BaseWrapper<T>>(T{std::forward<Args>(args)...});
}

Позволяет нам создавать объекты без необходимости использования специального конструктора внутри объекта:

struct Derived { // note the missing : Base
  int i;
};
auto p = make_bw<Derived>(42);

Это немного обманчивое решение, поэтому правильный ответ все равно будет полезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...