c++ - 如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?

标签 c++ c++17

我正在尝试通过可变参数模板传递多个初始值设定项列表以在适当的位置构造 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/

相关文章:

c++ - 如何根据参数指定中断 vector ?

c++ - 在我的文本编码器程序中找不到错误

c++ - 下面的初始化是如何良构的?

c++ - 了解复制初始化和隐式转换

c++ - 在 C++ 并行 PRNG 领域取得领先

c++ - 何时使用 `asio_handler_invoke`?

c++ - Qt5 应用程序不会在 Ubuntu 上绘制任何窗口

C++ 多态性 - 继承类的映射

c++ - 如何在移动到shared_ptr后调用std::function

c++ - 在 C++ 11 中将指针传递给临时变量?