传递派生列表以作为成员存储(Pass a list of derived types in order to store them as a member)

编程入门 行业动态 更新时间:2024-10-04 05:29:02
传递派生列表以作为成员存储(Pass a list of derived types in order to store them as a member)

我有一个类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))), ...); }

更多推荐

本文发布于:2023-08-04 20:04:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1422268.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:成员   列表   list   Pass   derived

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!