为什么没有分段元组构造? [英] Why is there no piecewise tuple construction?

查看:145
本文介绍了为什么没有分段元组构造?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准模板 std :: pair std :: array std :: tuple ,它的理由是他们应该有一个非常相似的功能集。



但是, , std :: pair 允许分段构造。也就是说,如果类型 T1 T2 可以从一组参数 a1 ,a2,... b1,b2,... ,那么道德上讲,我们可以成对

 pair< T1,T2> p(a1,a2,...,b1,b2,...)

。实际上,这是像这样的拼写:

  std :: pair< T1,T2& p(std :: piecewise_construct,
std :: forward_as_tuple(a1,a2,...),
std :: forward_as_tuple(b1,b2,...)

问题:为什么数组不存在同样的分段构造元组?有什么深刻的理由,还是这是一个明显的遗漏?例如,这将是很好的有:

  std :: tuple< T1,T2,T3& t(std :: piecewise_construct,
std :: forward_as_tuple(a1,a2,...),
std :: forward_as_tuple(b1,b2,...),
std :: forward_as_tuple(c1,c2,...));

有没有理由不能这样做? [ :]

(我确实有一种情况,初始化具有默认元素值的元组向量,我希望直接从参数中构造,而不必再次说明每个元组元素类型。)

解决方案


问题:为什么数组和元组不存在相同的分段构造?


我的回忆是分段构造被添加到 std :: pair 仅仅是一个原因:支持对元素的uses-allocator构造,即允许提供分配器并有条件地传递给元素,如果它们支持用分配器构造(参见标准中的[allocator.uses])。



在C ++ 0x过程中的一个点 std :: pair 的构造函数是现在的两倍,每个构造函数都有一个相应的allocator-extended版本, std :: allocator_arg_t 和一个分配器参数例如

  template< class T ,类U> 
struct pair {
pair();
pair(allocator_arg_t,const Alloc&);
template< class TT,class UU>
pair(TT&&&&&&&&&
template< class Alloc,class TT,class UU>
pair(allocator_arg_t,const Alloc&&&&&&&&&&
//等

有一个正在运行的笑话关于 std :: pair 的疯狂复杂性。将分配器传递给元素的支持从 std :: pair 中删除​​,并移动到 std :: scoped_allocator_adaptor 负责检测元素是否应该使用分配器构造(请参阅构造重载使用指向 std :: pair in [allocator.adaptor.members])。



分段构造的一个好结果是你可以做对象元素的emplace样式初始化,允许对不可移动,不可复制类型,但据我所知,这不是设计的目标。



所以原因 tuple 不支持它是发明的特性是为了简化,从C ++ 03中的一个非常简单的类型膨胀到笑股票在C ++ 0x,但做同样的 tuple 不被认为是重要的(这是新的C ++ 11反正)。此外,扩展 scoped_allocator_adaptor 以处理任意数量元素的元组会使该适配器太多更复杂。



对于 std :: array ,这是一个聚合类型(因为原因)所以添加一个构造函数 piecewise_construct_t 是不可能的,而不使它不是聚合。


The standard templates std::pair and std::array are special cases of std::tuple, and it stands to reason that they should have a very similar set of capabilities.

However, uniquely among the three, std::pair allows for piecewise construction. That is, if the types T1 and T2 can be constructed from a set of arguments a1, a2, ... and b1, b2, ..., then morally speaking we can make a pair

"pair<T1, T2> p(a1, a2, ..., b1, b2, ...)"

directly. Practically, this is spelt out as something like this:

std::pair<T1, T2> p(std::piecewise_construct,
                    std::forward_as_tuple(a1, a2, ...),
                    std::forward_as_tuple(b1, b2, ...));

Question: Why doesn't the same piecewise constructibility exist for arrays and tuples? Is there a profound reason, or is this a plain omission? For example, it would be nice to have:

std::tuple<T1, T2, T3> t(std::piecewise_construct,
                         std::forward_as_tuple(a1, a2, ...),
                         std::forward_as_tuple(b1, b2, ...),
                         std::forward_as_tuple(c1, c2, ...));

Is there a reason this cannot be done? [Edit: Or am I misunderstanding the purpose of piecewise construction entirely?]

(I do really have a situation in which I would like to initialize a vector of tuples with a defaulted element value which I would prefer to construct directly from the arguments, without spelling out each tuple element type again.)

解决方案

Question: Why doesn't the same piecewise constructibility exist for arrays and tuples?

My recollection is that piecewise construction was added to std::pair for one reason only: to support uses-allocator construction of the pair elements, i.e. to allow an allocator to be provided and conditionally passed to the elements if they support construction with an allocator (see [allocator.uses] in the standard).

At one point during the C++0x process std::pair had twice as many constructors as it does now, with every constructor having a corresponding "allocator-extended" version taking a std::allocator_arg_t and an allocator argument e.g.

template<class T, class U>
  struct pair {
    pair();
    pair(allocator_arg_t, const Alloc&);
    template<class TT, class UU>
      pair(TT&&, UU&&);
    template<class Alloc, class TT, class UU>
      pair(allocator_arg_t, const Alloc&, TT&&, UU&&);
    // etc.

There was something of a running joke (haha, only serious) about the insane complexity of std::pair. The support for passing allocators to the elements was removed from std::pair and moved into std::scoped_allocator_adaptor, which is responsible for detecting whether the elements should be constructed with an allocator (see the construct overloads taking a pointer to std::pair in [allocator.adaptor.members]).

A nice consequence of the piecewise construction is that you can do "emplace" style initialization of pair elements, allowing pairs of non-movable, non-copyable types, but as far as I know that was not the goal of the design.

So the reason tuple doesn't support it is that the feature was invented to simplify pair which had ballooned from a very simple type in C++03 to a laughing stock in C++0x, but doing the same for tuple was not considered as important (it was new for C++11 anyway). Also, extending scoped_allocator_adaptor to handle tuples of arbitrary numbers of elements would have made that adaptor much more complicated.

As for std::array, that's an aggregate type (because reasons) so adding a constructor taking piecewise_construct_t is not possible without making it a non-aggregate.

这篇关于为什么没有分段元组构造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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