C ++提供类模板的初始化器列表构造函数 [英] C++ Supply initializer-list constructor for class template
问题描述
我有一个模板参数为T的类模板Templ,而Templ类具有类型为T的数据成员,称为obj。我写了一个可变参数的构造函数模板,该参数将参数转发给obj的构造函数:
I have a class template Templ with template parameter T, and the Templ class has a data member of type T, called obj. I wrote a variadic constructor template which forwards the arguments to obj's constructor:
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 :: emplace
和 std :: make_shared
的作用。它们具有像我一样的可变函数,但没有覆盖init列表的替代项。出于某些原因。
Now I realized that type T may be a class with an init-list constructor, and I want it to be accessible via Templ. So I checked what std::list::emplace
and std::make_shared
do. They have a variadic function like mine, but they don't have overrides taking an init-list. For some reason.
第一个问题:为什么?我的意思是,如果我使用带有初始化列表ctor的T类,然后使用 std :: list< T>
怎么办?为什么list :: emplace没有采用initializer_list的版本?也许有充分的理由我也应该这样做...所以我想知道。
So first question: why? I mean, what if I use some class T with an init-list ctor, and then I use std::list<T>
? Why does list::emplace not have a version that takes an initializer_list? Maybe there's a good reason I should do it either... so I want to know.
此外,无论STL做什么,我都应该提供一个初始化列表ctor一样好的设计?我的意思是,就像变奏曲ctor,对不对?允许用户选择要与Templ<>一起使用的任何类型或类T,并直接调用为T定义的任何ctor。即使它是使用init列表的ctor。
Also, regardless of what the STL does - should I supply an init-list ctor as good design? I mean, it's just like the variadic ctor, right? Allowing the user to choose any type or class T to use with Templ<> and directly call any ctor defined for T. Even if it's a ctor taking an init-list.
推荐答案
转发 initializer_list
构造函数的问题是,除最琐碎的参数类型外,其他所有类型都不可推导(模板不一定总能猜出初始化列表的类型):
The problem with forwarding initializer_list
constructors is that all but the most trivial argument types aren't deducible (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< ...> {...}}
在大多数情况下,仅为基元提供它就没有多大意义了,当然也不为标准提供
Since you'd have to write m{std::initializer_list<...>{...}}
in most cases, there's not much point providing it just for primitives, and certainly not for the standard to do so.
如果您认为任何有趣的 initializer_list
参数很可能是针对容器类型的,则可以看看采用的方法(可选地)为模板(可能是包装容器)支持initializer_list构造。
If you think that any interesting initializer_list
arguments are likely to be for container types, you could look at the approach taken in Optionally supporting initializer_list construction for templates maybe wrapping containers.
这篇关于C ++提供类模板的初始化器列表构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!