Implicit conversion from int to vector?

狂风中的少年 提交于 2019-12-23 07:55:35

问题


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

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, i.e. does the same as would the code I would normally write:

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

How? Why?

Compiler: MSVC10.0


OK, seems it's an MSVC bug (yet another one). If someone can elaborate on the bug in an answer (i.e. summarize the cases where it is reproduced) I would gladly accept it


回答1:


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...

... but the compiler requires that the second overload, if the deduced type InputIterator is integral behaves as if it was a call to:

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>. 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).




回答2:


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. It's not auto casting from an int to a vector.




回答3:


This is actually an extension, not a 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.



来源:https://stackoverflow.com/questions/16427951/implicit-conversion-from-int-to-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!