这段代码片段:
enum {N = 10, M = 100};
vector<int> v(N, M);
由于以下错误,无法在Visual Studio 2013中编译通过:
error C2838: 'iterator_category' : 在成员声明中使用了非法的限定名称
出了什么问题?
这段代码片段:
enum {N = 10, M = 100};
vector<int> v(N, M);
由于以下错误,无法在Visual Studio 2013中编译通过:
error C2838: 'iterator_category' : 在成员声明中使用了非法的限定名称
出了什么问题?
由于不符合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);
vector
构造函数应该被禁用。然而,VS2013没有正确实现这一点。它试图使用需要两个输入迭代器的构造函数,这将是一个错误,而[...]
查看正在编译的函数模板实例化 'std::vector>::vector<,void>(_Iter,_Iter)'的引用
[...]>
gcc
和clang
的代码可以正常工作。根据C++11标准中的说明,我们知道该构造函数在重载决议中不应考虑:
这与草案C++11标准第23.2.3节“序列容器”第14段所述相符:用范围[first, last)中的内容构造容器。 如果InputIt未满足InputIterator,则此构造函数不参与重载决议,以避免与重载2产生歧义(自C++11以来)
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.