Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I initialise a std::vector<T*> from a list of instances?

Tags:

c++

I have some objects like this:

Obj o1{};
Obj o2{};
Obj o3{};
...

However, I also have another class Foo which has a std::vector<Obj*> as a member.

How can I initialise the vector from an arbitrary list?

I would like to construct Foo like this:

Foo f{o1, o3, o4};

I have tried this knowing that I can't have collections of references.

    class Foo {
    public:
        explicit Foo(std::initializer_list<Obj&> px) {
            for (auto& p : px) {
                fwds.push_back(&p);
            }
        }

        ...

    private:
        std::vector<Obj*> fwds;
    };

The error I get in this case is:

... include\initializer_list(25,1): error C2528:  'abstract declarator': pointer to reference is illegal
like image 443
quamrana Avatar asked Dec 03 '22 10:12

quamrana


2 Answers

With std::reference_wrapper, you might do:

explicit Foo(std::initializer_list<std::reference_wrapper<Obj>> px) {
    for (auto& p : px) {
        fwds.push_back(&p.get());
    }
}

Demo

Note: You might also want to promote your members to std::vector<std::reference_wrapper<Obj>> fwds;, which simplify the constructor too.

like image 101
Jarod42 Avatar answered Feb 15 '23 12:02

Jarod42


You could do it this way:

class Foo {
public:
    template <typename... Objs,
         std::enable_if_t<(std::is_base_of_v<Obj, Objs> && ...), int> = 0>
    explicit Foo(Objs&... o)
        : fwds{&o...}
    { }
private:
    std::vector<Obj*> fwds;
};

which in C++20 becomes:

class Foo {
public:
    explicit Foo(std::derived_from<Obj> auto&... o)
        : fwds{&o...}
    { }
private:
    std::vector<Obj*> fwds;
};
like image 38
Barry Avatar answered Feb 15 '23 10:02

Barry