c++ - 在通用模板代码中初始化聚合成员

标签 c++ templates c++14 language-lawyer aggregate-initialization

例如,

template <typename T>
struct node {
  T data;
  node* pnext;
};

template <typename T, typename... Us>
void func(Us&&... args) {
  // Initialize a node<T> with data initialized from args...
}

我能想到的方法及其局限性。

  1. node<T> v{ T(forward<Us>(args)...) } .这涉及copy-initialization如果 T 则无法正常工作是不可复制和不可移动的,例如 atomic类型。

  2. node<T> v{ {forward<Us>(args)...} } .这涉及copy-list-initialization如果所选的构造函数是显式的,它将无法工作。例如,node<unique_ptr<int>> n{ {new int()} }不起作用。

如果我能以某种方式直接初始化(例如,直接列表初始化)聚合成员,我想问题就解决了。然而,除了编写用户提供的构造函数之外,我没有发现这怎么可能,使node成为可能。非聚合类型,这是矫枉过正,我不愿意这样做。有什么想法吗?

最佳答案

C++14对这个困境没有有效的解决方案。好吧,不是在仍然使用聚合初始化的时候。如果你给node<T>一个可变构造函数,然后它可以将参数直接转发给成员初始化器:

template <typename T>
struct node {
  T data;
  node* pnext;

  template<typename ...Args>
  node(Args ...&&args) : data(std::forward<Args>(args)...) {}
};

因此允许您调用 node<T> v( T(forward<Us>(args)...) ) .当然,它不再是一个集合。

C++17 的保证省略规则允许 node<T> v{ T(forward<Us>(args)...) }不引起复制或移动。

关于c++ - 在通用模板代码中初始化聚合成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48944376/

相关文章:

c++ - 在运行时使用函数转换类型列表

c++ - 将 lambda 作为模板参数传递 : what type is actually deduced?

javascript - 构建 backbone.js 应用程序

c++ - 具有共享私有(private)数据的模板函数

c++ - 有效地计算体素数据的梯度

c++ - 使用 clang 从 C/C++ 头文件中提取函数声明

c++ - 如何像 std::string 一样为自定义 std::basic_string<> 特化类定义哈希类?

c++ - 使用 << 运算符构造 std::string

c++ - 解析 int 和 string

c++ - 获取数组中所有数字组合且无间隙的最快方法