C++ 为类模板提供初始值设定项列表构造函数

C++ Supply initializer-list constructor for class template

本文关键字:构造函数 列表 C++      更新时间:2023-10-16

我有一个带有模板参数 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做什么。它们有一个像我这样的可变参数函数,但它们没有采用初始化列表的覆盖。出于某种原因。

所以第一个问题:为什么?我的意思是,如果我使用带有初始化列表 ctor 的某个类 T 然后使用 std::list<T> 怎么办?为什么 list::emplace 没有需要initializer_list的版本?也许我应该这样做是有充分理由的......所以我想知道。

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

转发initializer_list构造函数的问题在于,除了最琐碎的参数类型之外,其他参数类型都不可推导(模板并不总是猜测初始值设定项列表类型(:

#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<...>{...}},因此仅为原语提供它没有多大意义,当然也不适合标准这样做。

如果您认为任何有趣的initializer_list参数都可能适用于容器类型,则可以查看可选支持模板的initializer_list构造可能包装容器中采用的方法。