C ++提供类模板的初始化器列表构造函数 [英] C++ Supply initializer-list constructor for class template

查看:107
本文介绍了C ++提供类模板的初始化器列表构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板参数为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆