我正在使用std::set
来保存Board
类型的成员,并且我希望迭代该集以进行无法与find方法一起使用的比较,因为将使用不同的条件进行排序经文定位。
1>c:\...\project.cpp(1140): error C2440: 'initializing' : cannot convert from 'std::_Tree_const_iterator<_Mytree>' to 'std::_Tree_const_iterator<_Mytree>'
1> with
1> [
1> _Mytree=std::_Tree_val<std::_Tset_traits<Board,std::greater<Board>,std::allocator<Board>,false>>
1> ]
1> and
1> [
1> _Mytree=std::_Tree_val<std::_Tset_traits<Board,std::less<Board>,std::allocator<Board>,false>>
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
事情是迭代器不应该是const。该方法不是const,该方法是在方法的本地创建的,我并没有将迭代器作为const。
Thing::Thing thisFunction(int action){
// snip
set<Board, less<Board>> openSet;
// snip
for(set<Board>::iterator ii = openSet.begin(); // line 1140
ii != openSet.end(); ii++){
// snip
}
这没有直接意义,因为迭代器没有被声明为const,所以它不应该试图考虑const。
分别为什么当我使用std::_tree
时,编译器会讨论std::set
答案 0 :(得分:4)
我认为你有一个比我在下面描述的更简单的问题......
尝试更改for
循环:
for (set<Board>::iterator ii = openSet.begin(); ii != openSet.end(); ii++) { //...
为:
for (set<Board, less<Board> >::iterator ii = openSet.begin(); ii != openSet.end(); ii++) { //...
因此编译器认为不需要进行转换。似乎还有其他事情发生在代码中,因为less<Board>
应该是默认的比较器。
如果您发布的错误多于第一行,那么事情会更清楚一些。
set::iterator
始终是VS 2010中的const_iterator。
如果要“修改”迭代器引用的元素,则需要从集合中删除该元素,创建新元素(不一定按该顺序)并将新元素插入集合中。
它执行此操作的方式隐藏在_Tree
模板类型中std::set
派生自_Tree
是为std::set
提供大部分实现的类型, std::multiset
,std::map
和std::multimap
- 这就是您在错误中看到_Tree
的引用的原因。 _Tree
类型如此声明iterator
(在<xtree>
标题中):
typedef _Tree_const_iterator<_Mybase>
const_iterator;
typedef typename _STD tr1::conditional<
_STD tr1::is_same<key_type, value_type>::value,
const_iterator,
_Tree_iterator<_Mybase> >::type iterator;
因此,如果键类型与值类型相同(例如对于std:set
,则迭代器是_Tree
的{{1}}的类型定义。< / p>
Scott Meyers在“Effective STL”,“Item 22:避免set和multiset中的就地密钥修改”中讨论了这一点,包括一些编译器将如何使用const_iterator样式的std :: set迭代器。
答案 1 :(得分:3)
问题比较简单,你不能指定一个
std::set<Board, std::greater<Board>>::iterator
到
std::set<Board>::iterator
因为实际上是 a
std::set<Board, std::less<Board>>::iterator
标准不保证这些类型相同,并且不保证它们之间会有转换。在实践中,这些总是不同的类型,并且没有转换。因此你的错误。
答案 2 :(得分:0)
std::set
是一个有序的容器,所以如果你允许迭代集合和muck以及其中项目的内部状态,你可能会导致排序顺序发生变化,从而将集合保留在不一致的状态。为防止出现这种情况,std::set::iterator::operator->
会返回const std::set::value_type*
而不是std::set::value_type*
。
因此,以下示例进行编译,但如果将Foo::bar
更改为非const成员函数,则编译将失败。
#include <set>
struct Foo
{
void bar() const {} // must be const
};
int main()
{
std::set<Foo> mySet;
for( std::set<Foo>::iterator it = mySet.begin(); it != mySet.end(); ++it ) {
it->bar();
}
}
编辑:
要修复原始错误,您只需在循环中调用const
个成员函数。如果确实需要改变集合中项目的状态,则不能在适当的位置进行。正如Michael Burr在他的answer中建议复制一样,删除原件,修改副本并将其重新插入到集合中。