使用迭代器的 std::vector 模板构造函数是否允许转换? [英] Is conversion allowed with std::vector's template constructor taking iterators?

查看:23
本文介绍了使用迭代器的 std::vector 模板构造函数是否允许转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 C++11 标准的第 23.3.6.2 节 [vector.cons] 中,如下所述:

 模板 向量(首先输入迭代器,最后输入迭代器,const 分配器&= 分配器());

<块引用>

9 效果:使用指定的分配器构造一个等于范围 [first,last) 的向量.
10 复杂性:仅对 T 的复制构造函数进行 N 次调用(其中 N 是 firstlast 之间的距离)并且如果迭代器没有重新分配first 和 last 属于前向、双向或随机访问类别.如果它们只是输入迭代器,它会对 T 的复制构造函数进行 N 次调用,并对 log(N) 次重新分配进行排序.

(此文本也存在于旧标准中).一方面,它不需要取消引用 InputIterator 应该导致存储在向量中的相同类型的值.另一方面,它讲述了使用复制构造函数,这意味着相同的类型.

我的问题是:如果可以在类型之间进行转换,那么在此构造函数中使用一系列不同类型的元素是否有效?最好参考标准.

例如,以下代码在 at ideone 中运行良好.它是由标准保证的,还是恰好 GCC 允许它?

#include <向量>#include 结构体{国际n;A(int n_) : n(n_) {}};int main() {int arr[] = {1,2,3,4,5,6,7,8,9,10};std::vectorint_vec(arr, arr+10);std::vectorA_vec(int_vec.begin(), int_vec.end());for( std::vector::iterator it=A_vec.begin(); it!=A_vec.end(); ++it )std::cout<<它->n <<" ";std::cout<

来自 C++ 2012 年 1 月草案:

<块引用>

§ 23.2.3/3 [sequence.reqmts] ....i 和 j 表示满足输入迭代器的迭代器要求和 指的是隐式转换为的元素value_type, [i, j) 表示有效范围....

X(i, j)
X a(i, j)
要求:T 应该是 EmplaceConstructible 到 X来自*我.对于vector,如果迭代器不满足forward迭代器要求(24.2.5),T 也应该是 MoveInsertable into X.范围 [i,j) 中的每个迭代器都应该被取消引用一次.
post: distance(begin(), end()) == distance(i, j) 构造一个序列容器等于范围 [i, j)

Coren 让我注意到您引用的部分:

<块引用>

§ 23.3.6.2/8 [vector.cons] template vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
效果:使用指定的分配器构造一个等于范围 [first,last) 的向量.
复杂性:仅对 T 的复制构造函数进行 N 调用(其中 N 是第一个和最后一个之间的距离),如果第一个和最后一个迭代器是前向、双向的,则不会重新分配,或随机访问类别.如果它们只是输入迭代器,它会对 T 的复制构造函数进行 N 次调用,并对 log(N) 次重新分配进行排序.

位于特定于向量的区域,技术上应该覆盖第一部分.但是,我相信这个对复制构造函数的引用是错误的,而且为了迂腐,提到复制构造函数是最大的复杂性,因此对复制构造函数的调用为 0(仅使用转换构造函数)在我看来是有效的.这没有我希望的那么清楚.

Xeo 让我注意到 C++ 标准核心语言活动问题,修订版 78 有一个问题 (535) 是关于如何在标准中关于复制构造的许多规定被表述为仅指复制构造函数."这显然是糟糕的措辞.应该检查标准中术语复制构造函数"的每次使用,以确定它是否严格适用于复制构造函数或任何用于复制的构造函数.(类似的问题适用于复制赋值运算符",它们与赋值运算符函数模板具有相同的关系.)"因此,纠正这种糟糕的措辞是他们的待办事项.

In the C++11 standard, Section 23.3.6.2 [vector.cons], the following is said:

   template <class InputIterator>
     vector(InputIterator first, InputIterator last,
            const Allocator& = Allocator());

9 Effects: Constructs a vector equal to the range [first,last), using the specified allocator.
10 Complexity: Makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories. It makes order N calls to the copy constructor of T and order log(N) reallocations if they are just input iterators.

(this text exists in the older standard as well). On one hand, it does not require that dereferencing an InputIterator should result in a value of the same type that is stored in the vector. On the other hand, it tells about using copy constructors, which sort of implies the same type.

My question is: is it valid to use a sequence of elements of different type with this constructor, provided that conversion between types is possible? References to the standard are desirable.

For example, the following code works fine at ideone. Is it guaranteed by the standard, or does just GCC happen to allow it?

#include <vector>
#include <iostream>

struct A {
    int n;
    A(int n_) : n(n_) {}
};

int main() {
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    std::vector<int> int_vec(arr, arr+10);
    std::vector<A> A_vec(int_vec.begin(), int_vec.end());

    for( std::vector<A>::iterator it=A_vec.begin(); it!=A_vec.end(); ++it )
        std::cout<< it->n <<" ";
    std::cout<<std::endl;
}

解决方案

From C++ Jan 2012 draft:

§ 23.2.3/3 [sequence.reqmts] ....i and j denote iterators satisfying input iterator requirements and refer to elements implicitly convertible to value_type, [i, j) denotes a valid range....

X(i, j)
X a(i, j)
Requires: T shall be EmplaceConstructible into X from *i. For vector, if the iterator does not meet the forward iterator requirements (24.2.5), T shall also be MoveInsertable into X. Each iterator in the range [i,j) shall be dereferenced exactly once.
post: distance(begin(), end()) == distance(i, j) Constructs a sequence container equal to the range [i, j)

Coren brought my attention that the section you quoted:

§ 23.3.6.2/8 [vector.cons] template <class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
Effects: Constructs a vector equal to the range [first,last), using the specified allocator.
Complexity: Makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories. It makes order N calls to the copy constructor of T and order log(N) reallocations if they are just input iterators.

is in the vector-specific area and technically should override the first section. However, I believe this reference to the copy constructor is in error, and to be pedantic, the mention of copy-constructors is in the complexity as a maximum, and thus 0 calls to the copy constructor (only using a conversion constructor) seems to me to be valid. This is less clear than I would wish.

Xeo brought my attention to the fact that C++ Standard Core Language Active Issues, Revision 78 has an issue (535) is about how in the standard "many of the stipulations about copy construction are phrased to refer only to "copy constructors."' and this is obviously poor wording. "each use of the term "copy constructor" in the Standard should be examined to determine if it applies strictly to copy constructors or to any constructor used for copying. (A similar issue applies to "copy assignment operators," which have the same relationship to assignment operator function templates.)" So, correcting this poor wording is on their to-do list.

这篇关于使用迭代器的 std::vector 模板构造函数是否允许转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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