c++ - 如何将可变参数放入具有继承的元素向量?
问题描述
我使用 c++ 17 并拥有下一组类
class A {
public:
virtual void fun() = 0;
};
class B : public A {
public:
void fun() override {
}
};
class C : public A {
public:
void fun() override {
}
};
我想要一个函数过程,它接受变量的变量列表并返回A的向量(一个基类)
std::unique_ptr<B> b1(new B());
std::unique_ptr<B> b2(new B());
std::unique_ptr<C> c1(new C());
std::unique_ptr<C> c2(new C());
auto vec = process<A>(b1, b2, c1, c2);
对于使用initializer_list我必须知道传递参数的确切类型。
我看不到使用 viriardic 模板的方法,因为我不知道如何正确解压缩参数。
template <typename T, typename... Rest>
std::vector<std::unique_ptr<T>> process(std::unique_ptr<T> t, std::unique_ptr<Rest>... rest) {
std::vector<std::unique_ptr<T>> A = process<std::unique_ptr<T>>(rest...);
std::vector<std::unique_ptr<T>> B = process(t);
std::vector<std::unique_ptr<T>> AB;
AB.reserve(A.size() + B.size());
AB.insert(AB.end(), A.begin(), A.end());
AB.insert(AB.end(), B.begin(), B.end());
return AB;
}
template <typename T>
std::vector<std::unique_ptr<std::unique_ptr<T>>> process(std::unique_ptr<T> t) {
return std::vector<std::unique_ptr<T>>{t};
}
template <typename T, typename... Rest>
std::vector<std::unique_ptr<T>> process(std::unique_ptr<Rest>... rest) {
std::vector<std::unique_ptr<T>> vector;
auto va = {rest...};
for (auto el : va) {
process(el);
}
return vector;
}
有没有简单的方法来实现一个接受可变参数并返回一个向量的函数?
解决方案
这是折叠表达式的一个很好的用例。
#include <memory>
#include <iostream>
#include <vector>
class A {
public:
virtual void fun() = 0;
};
class B : public A {
public:
void fun() override {
}
};
class C : public A {
public:
void fun() override {
}
};
template <typename T, typename... Args>
auto process(Args&&... args) {
std::vector<std::unique_ptr<T>> vec;
vec.reserve(sizeof...(Args));
(vec.emplace_back(std::move(args)), ...);
return vec;
}
int main() {
std::unique_ptr<B> b1(new B());
std::unique_ptr<B> b2(new B());
std::unique_ptr<C> c1(new C());
std::unique_ptr<C> c2(new C());
auto vec = process<A>(b1, b2, c1, c2);
}
请注意,这里我们窃取了 b1、b2、c1 和 c2 拥有的对象,并且它们已被移动到向量中。对于使用您的代码的人来说,这可能有点令人惊讶。
通常,当您想要移动或拥有某些东西时,您想在呼叫站点明确说明以避免混淆。
我们可以通过按值获取我们的论点来强制执行这一点。那么只有在调用站点使用时才可以使用std::unique_ptr
s调用。std::move
像这样的东西。
template <typename T, typename... Args>
auto process(Args... args) {
std::vector<std::unique_ptr<T>> vec;
vec.reserve(sizeof...(Args));
(vec.emplace_back(std::move(args)), ...);
return vec;
}
int main() {
std::unique_ptr<B> b1(new B());
std::unique_ptr<B> b2(new B());
std::unique_ptr<C> c1(new C());
std::unique_ptr<C> c2(new C());
auto vec = process<A>(std::move(b1), std::move(b2), std::move(c1), std::move(c2));
}
现在不移动原来的就不能调用函数了std::unique_ptr
,所以在调用处会很清楚b1、b2、c1、c2的内容已经被取走了。
推荐阅读
- ios - App Clip - 支持多个营业地点
- python - 如何解决这个涉及 Polyfit 的 NumPy 错误?
- javascript - 如何在js中对包含字符串的数字数组求和?
- spring-tool-suite - 如何在 STS 中配置 Open JDK 11?
- amazon-web-services - Django 错误:确保此值最多包含 5 个字符(它有 6 个)
- json - “消息”:“非法字符串偏移 'product_id'”,在 Laravel RESTfull API 中
- python - `object.from` 属性
- android - 是否可以从自定义视图调用 DialogFragment?
- log4j - 如何在纱线上配置 log4j?
- powershell - 适用于 Windows Server 2003 的 Powershell 调用命令