I have a class widget
.
I have an abstract class base
with derivates derived_a
, derived_b
, etc.
I want widget
to hold an arbitrary amount of objects that are derivated from base
in order to later 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 would 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 not user friendly at all, especially when providing multiple 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 usage along the lines of
widget w {derived_a(),
derived_b(),
derived_c(),
derived_a(),
derived_b(),
derived_c()};
so that widget
is provided with a list of rvalues that it then can turn into std::vector<unique_ptr<base>>
.
I have the impression that this can be achieved through templating the ctor, but, despite intensive googling, I have no clue on how to achieve my goal exactly.
Please note that the class template solution that would look tike this:
widget<derived_a,
derived_b,
derived_c,
derived_a,
derived_b,
derived_c> w;
Is undesirable, as I need to provide some deriveds with parameters.
Unfortunately, you cannot use initializer_list
, but you can use variadic template:
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;
};
Demo
or in C++17, with folding expression:
template <typename ... Ts>
explicit widget(Ts&&... params)
{
(members.emplace_back(std::make_unique<Ts>(std::forward<Ts>(params))), ...);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With