Информация об изменениях

Сообщение Re[2]: RAII vs RAII от 20.09.2018 16:28

Изменено 20.09.2018 16:42 rg45

Re[2]: RAII vs RAII
Здравствуйте, dipso, Вы писали:

D>Прошу прощения, не все ответы прочитал, нет столько времени, но...

D>Самый простой вариант — реализовать класс Tree пытаясь использовать
D>нынешнию RAII идеологию. Пишу прямо в тегах, сильно не пинайте.

  The Original Example
D>
D>template<typename T>
D>class Tree
D>{
D>public:

D>  using ptr_type = std::shared_ptr<T>;
D>  using weakptr_type = std::weak_ptr<T>;

D>Tree(ptr_type parent)
D>{
D>  SetParent(parent);
D>}

D>ptr_type Parent()
D>{
D>  return m_parent.lock();
D>} 

D>void SetParent(ptr_type parent) 
D>{
D>  m_parent = parent;

D>}

D>private:

D>weakptr_type m_parent;
D>std::vector<ptr_type> m_children;
D>};
D>


D>Нужно наследование от std::enable_shared_from_this.

D>Конструктор по умолчанию не важен.Хочу наследовать от
D>Tree. Включение против наследования не поможет.
D>Интересуют конструкторы.
D>В любом случае std::bad_weak_ptr.

Ну теперь хоть задача понятна более-менее

И сразу хочу отметить, что я вижу как раз то, о чем говорил здесь: http://rsdn.org/forum/cpp/7249960.1
Автор: rg45
Дата: 18.09.18
. А именно, не очень удачный дизайн. Судите сами: мы имеем проблему невозможности получения в конструкторе владеющего указателя на конструируемый класс. Вопрос: почему нам нужен этот указатель? А потому, что мы так запроектировали. А что нам мешает изменить этот дизайн? Да ничего!

https://ideone.com/HypKcm

template <typename T>
class Tree : public std::enable_shared_from_this<Tree<T>>
{
public:

  Tree() = default;

  template<typename...Args>
  explicit Tree(Args&&...args) : m_data(std::forward<Args>(args)...) {}
  
  std::shared_ptr<Tree> AddChild(const std::shared_ptr<Tree>& child)
  {
    using base = std::enable_shared_from_this<Tree>;
    m_children.push_back(child);
    child->m_parent = base::shared_from_this();
    return child;
  }

  template<typename...Args>
  std::shared_ptr<Tree> CreateChild(Args&&...args)
  {
    return AddChild(std::make_shared<Tree>(std::forward<Args>(args)...));
  }

private:
  T m_data;
  std::weak_ptr<Tree> m_parent;
  std::vector<std::shared_ptr<Tree>> m_children;
};

int main()
{
  const auto root_ptr = std::make_shared<Tree<int>>(0);
  root_ptr->CreateChild(1)->CreateChild(11)->CreateChild(111);
  root_ptr->CreateChild(2)->CreateChild(21)->CreateChild(211);
}
Re[2]: RAII vs RAII
Здравствуйте, dipso, Вы писали:

D>Прошу прощения, не все ответы прочитал, нет столько времени, но...

D>Самый простой вариант — реализовать класс Tree пытаясь использовать
D>нынешнию RAII идеологию. Пишу прямо в тегах, сильно не пинайте.

  The Original Example
D>
D>template<typename T>
D>class Tree
D>{
D>public:

D>  using ptr_type = std::shared_ptr<T>;
D>  using weakptr_type = std::weak_ptr<T>;

D>Tree(ptr_type parent)
D>{
D>  SetParent(parent);
D>}

D>ptr_type Parent()
D>{
D>  return m_parent.lock();
D>} 

D>void SetParent(ptr_type parent) 
D>{
D>  m_parent = parent;

D>}

D>private:

D>weakptr_type m_parent;
D>std::vector<ptr_type> m_children;
D>};
D>


D>Нужно наследование от std::enable_shared_from_this.

D>Конструктор по умолчанию не важен.Хочу наследовать от
D>Tree. Включение против наследования не поможет.
D>Интересуют конструкторы.
D>В любом случае std::bad_weak_ptr.

Ну теперь хоть задача понятна более-менее

И сразу хочу отметить, что я вижу как раз то, о чем говорил здесь: http://rsdn.org/forum/cpp/7249960.1
Автор: rg45
Дата: 18.09.18
. А именно, не очень удачный дизайн. Судите сами: мы имеем проблему невозможности получения в конструкторе владеющего указателя на конструируемый класс. Вопрос: почему нам нужен этот указатель? А потому, что мы так запроектировали. А что нам мешает изменить этот дизайн? Да ничего!

Выбрасываем метод SetParent, а вместо него добавляем пару методов: AddChild и CreateChild. После чего юзабельность не только не ухудшается, а становится даже лучше. И исходная проблема испаряется как сон на заре:

https://ideone.com/HypKcm

template <typename T>
class Tree : public std::enable_shared_from_this<Tree<T>>
{
public:

  Tree() = default;

  template<typename...Args>
  explicit Tree(Args&&...args) : m_data(std::forward<Args>(args)...) {}
  
  std::shared_ptr<Tree> AddChild(const std::shared_ptr<Tree>& child)
  {
    using base = std::enable_shared_from_this<Tree>;
    m_children.push_back(child);
    child->m_parent = base::shared_from_this();
    return child;
  }

  template<typename...Args>
  std::shared_ptr<Tree> CreateChild(Args&&...args)
  {
    return AddChild(std::make_shared<Tree>(std::forward<Args>(args)...));
  }

private:
  T m_data;
  std::weak_ptr<Tree> m_parent;
  std::vector<std::shared_ptr<Tree>> m_children;
};

int main()
{
  const auto root_ptr = std::make_shared<Tree<int>>(0);
  root_ptr->CreateChild(1)->CreateChild(11)->CreateChild(111);
  root_ptr->CreateChild(2)->CreateChild(21)->CreateChild(211);
}