简体   繁体   English

从int到vector的隐式转换?

[英]Implicit conversion from int to vector?

vector<T> has a constructor that takes the size of the vector, and as far as I know it is explicit , which can be proved by the fact that the following code fails to compile vector<T>有一个构造函数,它取了向量的大小,据我所知它是显式的 ,这可以通过以下代码无法编译的事实证明

void f(std::vector<int> v);
int main()
{
    f(5);
}

What I cannot understand and am asking you to explain is why the following code compiles 我无法理解并要求您解释的是以下代码编译的原因

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

Not only does it compile, it actually resizes graph to 5 and sets each element to a vector of five zeros, ie does the same as would the code I would normally write: 它不仅编译,它实际上将图形调整为5并将每个元素设置为五个零的向量,即与我通常编写的代码相同:

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

How? 怎么样? Why? 为什么?

Compiler: MSVC10.0 编译器:MSVC10.0


OK, seems it's an MSVC bug (yet another one). 好吧,似乎这是一个MSVC错误(还有一个)。 If someone can elaborate on the bug in an answer (ie summarize the cases where it is reproduced) I would gladly accept it 如果有人可以在答案中详细说明错误(即总结复制的情况),我很乐意接受

It is not really a bug. 这不是一个真正的错误。 The question is what could go wrong to allow the second piece of code while the first does not compile? 问题是在第一段代码不能编译的情况下允许第二段代码可能出错?

The issue is that while it seems obvious to you what constructor you want to call when you do: 问题在于,当您执行以下操作时,您想要调用的构造函数似乎很明显:

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

it is not so clear for the compiler. 编译器不太清楚。 In particular there are two constructor overloads that can potentially accept the arguments: 特别是有两个构造函数重载可以接受参数:

vector(size_type,const T& value = T());

template <typename InputIterator>
vector(InputIterator first, InputIterator last);

The first one requires the conversion of 5 to size_type (which is unsigned), while the second is a perfect match, so that will be the one picked up by the compiler... 第一个需要将5转换为size_type (无符号),而第二个是完美匹配,因此将是编译器选择的那个...

... but the compiler requires that the second overload, if the deduced type InputIterator is integral behaves as if it was a call to: ...但是编译器要求第二次重载,如果推断的类型InputIterator是积分的,就好像它是一个调用:

vector(static_cast<size_type>(first),static_cast<T>(last))

What the C++03 standard effectively mandates is that the second argument is explicitly converted from the original type int to the destination type std::vector<int> . C ++ 03标准有效强制要求的是第二个参数从原始类型int 显式转换为目标类型std::vector<int> Because the conversion is explicit you get the error. 因为转换是显式的,所以您会收到错误。

The C++11 standard changes the wording to use SFINAE to disable the iterator constructor if the argument is not really an input iterator, so in a C++11 compiler the code should be rejected (which is probably the reason some have claimed this to be a bug). 如果参数不是真正的输入迭代器,C ++ 11标准改变措辞使用SFINAE来禁用迭代器构造函数,因此在C ++ 11编译器中应该拒绝代码(这可能是某些人声称这个的原因)成为一个错误)。

To me it looks like it's calling this constructor: 对我来说,它看起来像是在调用这个构造函数:

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

I'm not sure where explicit comes into it, because the constructor takes multiple parameters. 我不确定在哪里explicit ,因为构造函数需要多个参数。 It's not auto casting from an int to a vector. 它不是从int自动转换为向量。

This is actually an extension, not a bug. 这实际上是一个扩展,而不是一个bug。

The constructor being invoked is the one that takes two iterators (but really, the signature will match any two parameters of the same type); 被调用的构造函数是带有两个迭代器的构造函数(但实际上,签名将匹配任何两个相同类型的参数); it then invokes a specialization for when the two iterators are actually int , which explicitly constructs a value_type using the value of end and populates the vector with begin copies of it. 然后,当两个迭代器实际上是int ,它调用一个特化,它使用end的值显式构造一个value_type ,并用它的begin副本填充向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM