【问题标题】:C++ Supply initializer-list constructor for class templateC++ 为类模板提供初始化列表构造函数
【发布时间】:2013-02-11 02:14:19
【问题描述】:

我有一个带有模板参数 T 的类模板 Templ,而 Templ 类有一个类型为 T 的数据成员,称为 obj。我写了一个可变参数构造函数模板,它将参数转发给 obj 的构造函数:

template <class T>
class Templ
{
public:
     template <class... Args> explicit Templ (Args&&... args)
     : obj (std::forward<Args>(args)...)
     {
     }
private:
     T obj;
};

现在我意识到类型 T 可能是一个带有 init-list 构造函数的类,我希望它可以通过 Templ 访问。所以我检查了std::list::emplacestd::make_shared 做了什么。他们有一个像我一样的可变参数函数,但他们没有覆盖初始化列表。不知为何。

所以第一个问题:为什么?我的意思是,如果我使用带有 init-list ctor 的某个类 T,然后我使用 std::list&lt;T&gt; 怎么办?为什么 list::emplace 没有采用 initializer_list 的版本?也许我也应该这样做是有充分理由的……所以我想知道。

另外,不管 STL 做什么——我应该提供一个 init-list ctor 作为好的设计吗?我的意思是,它就像可变参数 ctor,对吧?允许用户选择任何类型或类 T 与 Templ 一起使用并直接调用为 T 定义的任何 ctor。即使它是一个采用 init-list 的 ctor。

【问题讨论】:

  • 你的第一个问题是一个很好的问题,但是其他三个问题应该是单独的帖子。
  • @VaughnCato 我把其中一个分开了。我可以在 20 分钟内发布一次,所以我无法修复其余的……直到下一次
  • 完成,现在只有 1 个问题

标签: c++ c++11 variadic-templates initializer-list make-shared


【解决方案1】:

转发initializer_list 构造函数的问题在于,除了最微不足道的参数类型之外的所有参数类型都不可推导出(Templates don't always guess initializer list types):

#include <map>
template<typename T> struct U {
   T t;
   template<typename...A> explicit U(A&&...a): t(std::forward<A>(a)...) {}
   template<typename L, typename = typename std::enable_if<
      std::is_constructible<T, std::initializer_list<L>>::value>::type>
      explicit U(std::initializer_list<L> l): t(l) {}
};
U<std::map<int, int>> m{{{0, 1}, {2, 3}}};  // fails, couldn't deduce 'L'

由于在大多数情况下您必须编写 m{std::initializer_list&lt;...&gt;{...}},因此只为原语提供它并没有多大意义,当然也不适合标准这样做。

如果您认为任何有趣的initializer_list 参数都可能用于容器类型,您可以查看Optionally supporting initializer_list construction for templates maybe wrapping containers 中采用的方法。

【讨论】:

  • 我不希望包装容器,但我确实想支持一个具有 init-list ctor 的类。哪些情况下扣款无效?如果用作模板参数的类有一个 ctor,它采用原始类型变量的初始化列表,或者我定义的类的对象的初始化列表(不是一对或容器或类似的东西),它会工作吗?另外,我必须使用 enable_if 吗?如果我不这样做会怎样?
  • @fr33domlover 如果您的初始化程序是{x1, x2, ...} 的形式,其中所有x 都是相同类型的prvalue 表达式,那么您很好;问题是如果你有嵌套的大括号。如果要使用统一初始化,enable_if 是必需的; initializer_list 构造函数是贪婪的 (13.3.1.7)。
  • 我们当然需要一个用于下一个 c++ 的 initializer_tuple 内在类型,它允许完美地转发大括号初始化列表,无论它们是同质的还是异质的。
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-06
  • 1970-01-01
  • 2011-01-06
  • 2017-03-07
相关资源
最近更新 更多