我有一个类widget 。 我有一个抽象类库,派生的是derived_a , derived_b等。
我希望widget可以保存从base派生的任意数量的对象,以便稍后以多态方式使用它们。
我的第一次尝试看起来像这样:
#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; };会被称为这样:
std::vector<std::unique_ptr<base>> v; v.push_back(std::move(std::make_unique<derived_a>())); widget w (std::move(v));但是,这个解决方案难以接受冗长而且用户友好,特别是在提供多种类型时:
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)};相反,我更喜欢使用的方式
widget w {derived_a(), derived_b(), derived_c(), derived_a(), derived_b(), derived_c()};这样widget就会提供一个rvalues列表,然后它可以变成std::vector<unique_ptr<base>> 。 我的印象是,这可以通过模仿ctor来实现,但是,尽管谷歌搜索量很大,但我并不知道如何准确地实现我的目标。
请注意,类模板解决方案看起来像这样:
widget<derived_a, derived_b, derived_c, derived_a, derived_b, derived_c> w;是不可取的,因为我需要提供一些参数派生。
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.
最满意答案
不幸的是,你不能使用initializer_list ,但你可以使用variadic模板:
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; };演示
或者在C ++ 17中,使用折叠表达式:
template <typename ... Ts> explicit widget(Ts&&... params) { (members.emplace_back(std::make_unique<Ts>(std::forward<Ts>(params))), ...); }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))), ...); }更多推荐
发布评论