为什么枚举类型不能作为参数在这个向量构造函数中使用?

14

这段代码片段:

enum {N = 10, M = 100};

vector<int> v(N, M);

由于以下错误,无法在Visual Studio 2013中编译通过:

error C2838: 'iterator_category' : 在成员声明中使用了非法的限定名称

出了什么问题?


2
这个问题似乎gcc和clang都可以,看起来像是一个bug。 - Shafik Yaghmour
我强烈怀疑VS有bug.. - Marco A.
3个回答

12

由于不符合C ++11标准(使用_HAS_CPP0X定义为1),因此在VS2012和VS2013中都存在错误:

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

对于本条款和第21条所定义的每个序列:

- 如果 InputIterator 是整数类型,则构造函数 template <class InputIterator> X(InputIterator f, InputIterator l, const Allocator& a = Allocator())应产生与以下相同的效果:

X(static_cast<typename X::size_type>(f), static_cast<typename X::value_type>(l), a)

但是C++11 23.2.3 [sequence.reqmts]/14中提到:

对于本条款和第21条所定义的每个序列容器:

- 如果使用不符合输入迭代器的类型InputIterator调用模板构造函数template <class InputIterator> X(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()),则该构造函数不得参与重载决议。

那个构造函数根本不应该被考虑

更多信息请参见:https://dev59.com/UmXWa4cB1Zd3GeqPLUl5#12432482

作为解决方法,您可以“帮助重载决议”,例如:

std::vector<int> v(static_cast<std::vector<int>::size_type>(N), M);

10
自从C++11以来,如果两个参数不是迭代器类型,接受两个输入迭代器的vector构造函数应该被禁用。然而,VS2013没有正确实现这一点。

2
这是Visual Studio 2013的一个bug,从生成的错误信息(现场查看)来看,这只是其中的一小部分:

[...]

查看正在编译的函数模板实例化 'std::vector>::vector<,void>(_Iter,_Iter)'的引用

[...]>

它试图使用需要两个输入迭代器的构造函数,这将是一个错误,而gccclang的代码可以正常工作。根据C++11标准中的说明,我们知道该构造函数在重载决议中不应考虑:

用范围[first, last)中的内容构造容器。 如果InputIt未满足InputIterator,则此构造函数不参与重载决议,以避免与重载2产生歧义(自C++11以来)

这与草案C++11标准第23.2.3节“序列容器”第14段所述相符:

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.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接