从int到vector的隐式转换

Implicit conversion from int to vector?

本文关键字:转换 vector int      更新时间:2023-10-16

vector<T>有一个接受向量大小的构造函数,据我所知,它是显式的,以下代码无法编译

可以证明这一点
void f(std::vector<int> v);
int main()
{
    f(5);
}

我不能理解的是,我要求你解释为什么下面的代码编译

std::vector<std::vector<int>> graph(5, 5);

不仅可以编译,它实际上将图形的大小调整为5,并将每个元素设置为五个0的向量,也就是说,与我通常编写的代码相同:

std::vector<std::vector<int>> graph(5, std::vector<int>(5));

如何?为什么?

编译器:MSVC10.0


好吧,似乎这是一个MSVC的错误(又一个)。如果有人能在回答中详细说明这个bug(即总结它被复制的情况),我将很乐意接受

这并不是一个真正的bug。问题是什么可能出错,允许第二段代码,而第一个不能编译?

问题是,当你这样做时,你想调用的构造函数似乎很明显:

std::vector<std::vector<int>> graph(5, 5);

对于编译器来说不是很清楚。具体来说,有两种构造函数重载可能接受实参:

vector(size_type,const T& value = T());
template <typename InputIterator>
vector(InputIterator first, InputIterator last);

第一个需要将5转换为size_type(这是无符号的),而第二个是一个完美匹配,因此它将被编译器拾取…

…但是,如果推导出的类型InputIterator是整型,则编译器要求第二次重载的行为就像调用

一样:
vector(static_cast<size_type>(first),static_cast<T>(last))
c++ 03标准有效地规定了第二个参数是,显式地将从原始类型int转换为目标类型std::vector<int>。因为转换是显式的,所以会得到错误。

c++ 11标准改变了措辞,如果参数不是一个真正的输入迭代器,使用SFINAE来禁用迭代器构造函数,所以在c++ 11编译器中,代码应该被拒绝(这可能是一些人声称这是一个bug的原因)。

对我来说它好像在调用这个构造函数:

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

我不确定explicit在哪里,因为构造函数接受多个参数。它不能从int类型自动转换为vector类型

这实际上是一个扩展,而不是一个bug。

被调用的构造函数是带两个迭代器的构造函数(但实际上,签名将匹配任何两个相同类型的形参);然后,当两个迭代器实际上是int时,它调用一个特化,该特化使用end的值显式地构造一个value_type,并用它的begin副本填充向量。