我正在尝试通过可变参数模板传递多个初始值设定项列表以在适当的位置构造 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};
关于c++ - 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58338695/