c++ - 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?
问题描述
我正在尝试通过可变参数模板传递多个初始值设定项列表以在适当位置构造 std::array。
但是我找不到可以编译的版本(C++ 17)。
考虑以下代码:
struct TwoInts {
TwoInts(int x, int y)
: a{x}
, b{y}
{}
int a,b;
};
template<typename T, int S>
struct Holder {
template<typename... Args>
Holder(Args&&... args) : m({{std::forward<Args>(args)...}}) {}
//Deleted for clarity of the example:
Holder(const Holder& o) = delete;
Holder(Holder&& o) = delete;
std::array<T,S> m;
};
我们可以执行以下初始化:
TwoInts a = {1,2};
std::array<TwoInts,1> b{{{1,2}}};
std::array<TwoInts,2> c{{{1,2},{3,4}}};
Holder<int,1> d{1};
Holder<int,2> e{1,2};
但是如何修改示例以使其工作?
Holder<TwoInts,1> f{{{1,2}}};
Holder<TwoInts,2> f{{{1,2},{3,4}}};
Gcc 和 clang 找不到匹配的构造函数。
解决方案
您可以明确地说明参数类型,而不是隐式传递std::initializer_list
s:
Holder<TwoInts,1> f{TwoInts{1, 2}};
Holder<TwoInts,2> e{TwoInts{1,2}, TwoInts{3,4}};
这是由于std::initializer_list
s 会产生所谓的“非推导”上下文,因此您不能使用std::initializer_list
s 将它们传递给模板构造函数(因为该语言不允许您显式确定构造函数模板的模板类型)。
请注意,在std::array<TwoInts,1> b{{{1,2}}};
您不使用std::initializer_list
,而是执行聚合初始化,并且在 中Holder<int,1> d{1};
,您只需传递一个int
,这可以很好地进行演绎。
如果TwoInt
对象不可移动/复制构造,则可以将它们变成聚合;
struct TwoInts {
TwoInts(const TwoInts&) = delete;
TwoInts(TwoInts&&) = delete;
int a,b;
};
然后在整个过程中使用聚合初始化。持有者构造函数应该如下所示;
template<typename... Args>
Holder(Args&&... args) : m{{std::forward<Args>(args)...}} {}
// ^ no parentheses ... neither ^
你可以初始化
Holder<TwoInts,1> f{1, 2};
Holder<TwoInts,2> e{1,2, 3,4};
推荐阅读
- python-3.x - RaspberryPI4-ARM 上的多处理或多线程?
- github - 我如何从 github 克隆 apache-superset 并在我的本地系统中运行它
- c++ - fp.read((char*)&cont,sizeof(contact)) 在 C++ 中做了什么
- python - 无法将字符串转换为浮点数:'1,6800'
- c# - 如何使用 Coded UI 在运行时检测坐标位置的测试控件?
- r - For循环遍历dplyr管道
- docker - 即使在机器移除后,Docker Toolbox 也不会更新更改
- algorithm - 基于用户约束的锦标赛时间表创建算法
- excel - VBA将变量着色为双值类型
- javascript - 如何在我的 javascript 文件中从“node_modules”导入或使用已安装的模块