Все мы знаем и любим умные указатели за их безопасность и скорость, но необходимость вызывать такие функции меня беспокоит:

void TreeNode::addChild(unique_ptr<TreeNode> newChild){
    children_.push_back(std::move(newChild));
}
//This has to be called like so:

node.addChild(unique_ptr<TreeNode>(new TreeNode(10));

Я считаю его излишне многословным и длинным. Это действительно лучший способ делать что-то? Разве я не могу просто передать необработанный указатель и создать свой unique_ptr внутри addChild? Какие есть альтернативы и каковы преимущества такого многословия?

РЕДАКТИРОВАТЬ: Я хотел добавить, что TreeNode может быть производным от, поэтому просто реализовать addChild(int arg) недостаточно. Но

3
iFreilicht 25 Апр 2014 в 15:23

3 ответа

Лучший ответ
  • Вы можете сделать следующее:

    template<typename...Ts>
    void TreeNode::emplaceChild(Ts&&...args){
        children_.emplace_back(make_unique<TreeNode>(std::forward<Ts>(args)...));
    }
    

    А потом:

    node.emplaceChild(10);
    
  • Чтобы указать Тип добавляемого дочернего элемента, вы можете использовать в качестве замены:

    template<typename T, typename...Ts>
    void TreeNode::emplaceChild(Ts&&...args) {
        children_.emplace_back(make_unique<T>(std::forward<Ts>(args)...));
    }
    

    А потом:

    node.emplaceChild<TreeNode>(10);
    
3
Jarod42 25 Апр 2014 в 12:21

В C ++ 14 вы можете использовать функцию std::make_unique.

В C ++ 11 реализуйте это самостоятельно, например:

#include <memory>

struct X { X(int, int); };

void foo(std::unique_ptr<X>);

template<class T, class... Args>
inline std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

int main() {
    foo(make_unique<X>(1, 2));
}
4
Maxim Egorushkin 25 Апр 2014 в 11:37

Вы можете использовать typedef (который заменен на using в C ++ 11):

using TreeNodeUP = std::unique_ptr<TreeNode>;

Чтобы упростить код:

void TreeNode::addChild(TreeNodeUP newChild);

В качестве альтернативы, если у вас есть контроль над типом TreeNode, можно поместить typedef внутри класса и назвать его UP или что-то подобное короткое и использовать

void TreeNode::addChild(TreeNode::UP newChild);

Обратите внимание, что мне лично не нравятся эти typedef, я предпочитаю более подробный вариант написания std::unique_ptr, и я не обнаружил, что это действительно проблема.

0
Daniel Frey 25 Апр 2014 в 11:49