Smart Pointer Polymorphism in Collections

I am trying to initialize a collection of pointers to a class Athrough a list of initializers. However, the initializer list cannot use the link as a template type.

I have the following code.

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
#include <initializer_list>
#include <memory>

struct A
{
    virtual void f() const noexcept { std::cout << "A"; }
};

struct B : public A
{
    virtual void f() const noexcept override { std::cout << "B"; }
};

class Test
{
    std::vector<std::shared_ptr<A>> vec;
public:
    Test(const std::initializer_list<A>& list)
    //Test(const std::initializer_list<A&>& list) <------ Solution?
    {
        for (auto& x : list)
            vec.push_back(std::make_shared<A>(x));
    }
    void print()
    {
        std::for_each(vec.begin(), vec.end(), [](auto x) { x->f(); });
    }
};

int main()
{
    Test test = { A(), B() };
    test.print();
}

The code prints:

AA

It should print:

AB

Is there an easy way to do this without creating pointers in the calling method?

A related article ( How to implement polymorphism using std :: shared_ptr? ) Did not help solve this problem.

+4
source share
3 answers

std::initializer_list<T> , . , std::make_shared<A> A, , A. .

, , , .

: . WhozCraig :

template<class... Args>
Test(Args&&... args) :
    vec { std::make_shared<std::remove_reference_t<Args>>(std::forward<Args>(args))... }
{
}
+3

, std::make_shared<A>(). B A A.

, , :

struct Foo {
    template<typename... Args>
    Foo(Args... args) :
        vec{std::make_shared<Args>(std::move(args))...}
    {}

private:
    std::vector<std::shared_ptr<A>> vec;
};
+2

shared_ptr

        vec.push_back(std::make_shared<A>(x));

No matter what xit was, you created a new one Awith your meanings.

You probably want to create shared_ptr<A>and pass a pointer from x.get()to the new emptyshared_ptr<A>

+1
source

Source: https://habr.com/ru/post/1671169/


All Articles