14

This code fragment:

enum {N = 10, M = 100};

vector<int> v(N, M);

fails to compile with Visual Studio 2013, due to the following error:

error C2838: 'iterator_category' : illegal qualified name in member declaration

What's wrong with it?

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Paul Jurczak
  • 7,008
  • 3
  • 47
  • 72

3 Answers3

12

It's a bug in both VS2012 and VS2013 since it's not conforming to the C++11 standard (with _HAS_CPP0X defined as 1):

C++03 23.1.1 [lib.sequence.reqmts]/9 says:

For every sequence defined in this clause and in clause 21:

— the constructor template <class InputIterator> X(InputIterator f, InputIterator l, const Allocator& a = Allocator()) shall have the same effect as:

X(static_cast<typename X::size_type>(f), static_cast<typename X::value_type>(l), a) if InputIterator is an integral type.

but from C++11 23.2.3 [sequence.reqmts]/14:

For every sequence container defined in this Clause and in Clause 21:

— If the constructor template <class InputIterator> X(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.

That constructor should not have been considered at all

More here: https://stackoverflow.com/a/12432482/1938163

As a workaround you could "help the overload resolution a bit", e.g.

std::vector<int> v(static_cast<std::vector<int>::size_type>(N), M);
Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
10

Since C++11 the vector constructor accepting two InputIterators should be disabled if the two arguments aren't iterators. VS2013 fails to implement this correctly.

pmr
  • 58,701
  • 10
  • 113
  • 156
2

This is a Visual Studio 2013 bug, from the error being generated (see it live), this is just a small portion:

[...]

see reference to function template instantiation 'std::vector>::vector<,void>(_Iter,_Iter)' being compiled

[...]>

It is attempting to use the constructor that takes two input iterators. Which would be a bug, both gcc and clang are fine with this code.

We can that in C++11 that constructor should not be considered:

Constructs the container with the contents of the range [first, last). This constructor does not participate in overload resolution if InputIt does not satisfy InputIterator, to avoid ambiguity with the overload 2 (since C++11)

This agrees with the draft C++11 standard section 23.2.3 Sequence containers paragraph 14 which says:

If the constructor

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

is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740