将 initializer_list 个指针转换为 unique_ptr 个向量

Convert initializer_list of pointers to vector of unique_ptr

我创建了这个 class,它代表一组形状:

class CompoundShape : public Shape {
    private:
    std::vector<std::unique_ptr<Shape>> shapes;

    public:
    CompoundShape(std::initializer_list<Shape *> shapes) : shapes(shapes) {}

    void draw() {
        for_each(shapes.begin(), shapes.end(), [](auto &shape) { shape->draw(); });
    }
};

classShape还有另一个childclass,SimpleShape。理想情况下,我想像这样初始化一个 CompoundShape,而不必担心之后释放指向形状的指针:

CompoundShape shape = {
    new SimpleShape(...),
    new SimpleShape(...),
    new CompoundShape{...},
    ...
}

我认为唯一的问题是在 CompoundShape 构造函数中,我尝试在其中执行 shapes(shapes) 这当然行不通,因为 std::vector<std::unique_ptr<Shape>> 不能用 std::initializer_list<Shape *> shapes.

初始化

实现此转换的最佳方式是什么?

遗憾的是我们无法使用 std::initializer_list<std::unique_ptr<Shape>>

您仍然可以使用带有 2 个迭代器的 vector 构造函数来进行(不是那么明确的)转换:

CompoundShape(std::initializer_list<Shape *> shapes) : shapes(shapes.begin(), shapes.end()) {}

Demo

向量构造函数会做类似于

的事情
template <typename T>
template <typename It> // SFINAE to avoid to conflict with vector(std::size_t, T) when T=size_t
std::vector<T>::vector<T>(It begin, It end) :
    m_size(std::distance(begin, end)),
    m_capacity(m_size),
    m_data(allocate<T>(m_size))
{
    std::size_t i = 0;
    for (auto it = begin; it != end; ++it, ++i) {
        new (&data[i]) T(*it); // placement new, calling constructor deferencing iterator
    }
}

所以在你的情况下

std::initializer_list<Shape *>::iterator it /* = .. */;
Shape* shape = *it;
new (&data[i]) std::unique_ptr<Shape>(shape);