Pass the list of derivatives to be stored as a member

I have a class widget.
I have an abstract class basewith derivatives derived_a, derived_betc.

I want to widgetcontain an arbitrary number of objects that were obtained from base, so that I can subsequently use them polymorphically.

My first attempt looks like this:

#include <vector>
#include <ostream>
#include <iostream>
#include <memory>

class widget {
public:
    explicit widget(std::vector<std::unique_ptr<base>>&& params) :
    members {std::move (params)}
    {            
    }

private:
    std::vector<std::unique_ptr<base>> members;
};

And it will be called like this:

std::vector<std::unique_ptr<base>> v;
v.push_back(std::move(std::make_unique<derived_a>()));
widget w (std::move(v));

However, this solution seams unnessesarry verbose and is not user-friendly at all, especially when providing several types:

std::vector<std::unique_ptr<base>> v;
v.push_back(std::move(std::make_unique<derived_a>()));
v.push_back(std::move(std::make_unique<derived_b>()));
v.push_back(std::move(std::make_unique<derived_c>()));
v.push_back(std::move(std::make_unique<derived_a>()));
v.push_back(std::move(std::make_unique<derived_b>()));
v.push_back(std::move(std::make_unique<derived_c>()));
widget w {std::move(v)};

Instead, I would prefer using row by row

widget w {derived_a(), 
          derived_b(), 
          derived_c(), 
          derived_a(), 
          derived_b(), 
          derived_c()};

widget r, std::vector<unique_ptr<base>>.
, , , Google, , .

, , :

widget<derived_a, 
       derived_b, 
       derived_c, 
       derived_a, 
       derived_b, 
       derived_c> w;

, .

+4
1

, initializer_list, :

class widget {
public:
    template <typename ... Ts>
    explicit widget(Ts&&... params) 
    {
        int dummy[] =
            {0, (members.emplace_back(std::make_unique<Ts>(std::forward<Ts>(params))), 0)...};
        static_cast<void>(dummy); // avoid unused variable warning
    }

private:
    std::vector<std::unique_ptr<base>> members;
};

++ 17, :

    template <typename ... Ts>
    explicit widget(Ts&&... params) 
    {
        (members.emplace_back(std::make_unique<Ts>(std::forward<Ts>(params))), ...);
    }
+5

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


All Articles