C++ std::set::迭代器转换错误

C++ std::set::迭代器转换错误,c++,visual-studio-2010,set,C++,Visual Studio 2010,Set,我正在使用一个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>

我正在使用一个
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
1>c:\…\project.cpp(1140):错误C2440:“初始化”:无法从“std::\u Tree\u const\u iterator”转换为“std::\u Tree\u const\u iterator”
1> 与
1>          [
1> _Mytree=std::_Tree\u val
1>          ]
1> 及
1>          [
1> _Mytree=std::_Tree\u val
1>          ]
1> 没有构造函数可以采用源类型,或者构造函数重载解析不明确
问题是迭代器不应该是常量。方法不是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 
    }
Thing::Thing this函数(int操作){
//剪断
集开集;
//剪断
for(set::iterator ii=openSet.begin();//第1140行
ii!=openSet.end();ii++){
//剪断
}

这并不是直接意义上的,因为迭代器没有声明const,所以它不应该试图考虑const .< /p>


另外,当我使用
std::set

时,为什么编译器要谈论
std::_tree
,我想你有一个比我下面描述的简单得多的问题

尝试从以下位置更改
for
循环:

for (set<Board>::iterator ii = openSet.begin(); ii != openSet.end(); ii++) { //...
因此,如果键类型与值类型相同(例如对于
std:set
),则迭代器类型定义为
\u树的
常量迭代器


Scott Meyers在“有效STL”、“第22项:避免集合和多集合中的就地键修改”中对此进行了讨论,包括一些编译器将如何为std::set使用const_迭代器样式的迭代器。

std::set
是一个有序容器,因此如果允许您在集合上迭代,并破坏其中项的内部状态,则可能会导致排序顺序发生更改,从而使集合处于不一致的状态。为防止出现这种情况,
std::set::iterator::operator->
返回一个
const std::set::value\u type*
而不是
std::set::value\u type*

因此,下面的示例进行编译,但如果将
Foo::bar
更改为非常量成员函数,编译将失败

#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();
  }
}
#包括
结构Foo
{
void bar()常量{}//必须是常量
};
int main()
{
std::设置mySet;
对于(std::set::iterator it=mySet.begin();it!=mySet.end();++it){
it->bar();
}
}
编辑:

若要修复原始错误,只需在循环中调用
const
成员函数。如果确实需要更改集合中项目的状态,则不能就地执行。正如Michael Burr在其“制作副本”中所建议的那样,删除原始副本,修改副本并将其重新插入集合中。

问题相对简单,您可以无法分配

std::set<Board, std::greater<Board>>::iterator 
std::set::迭代器

std::set::迭代器
因为那实际上是一个

std::set::迭代器

标准不保证这些类型是相同的,也不保证它们之间会有转换。实际上,这些类型总是不同的,并且没有转换。因此,您的错误。

@fontanini:您不再需要
符号之间的空格。为了帮助您,我们需要完整的错误信息年龄。这可以在“输出”窗口中找到,但在“错误”窗口中找不到。“错误”窗口只显示每个错误的摘要。在这种情况下,我们需要更多。@gardian06:错误消息清楚地表明问题中的代码在一个非常重要的方面与您的实际代码不同。请不要这样做。对这个问题做一个小的演示,这个问题实际上在将来会有您的问题。-1用于雁行追逐。我不想这样做删除它们我想用一个
操作符==
对它们进行比较,该操作符使用与我使用的排序操作符不同的逻辑used@gardian06:那么就使用
const_迭代器吧。关于VS2010
std::set::begin()
返回一个
常量迭代器
,但它似乎不像我刚才所说的那样(re)尝试过。@hmjd:你尝试过什么?它声明了名称
std::iterator
,但引用的元素是
const
。你是否尝试过修改迭代器引用的项?@MichaelBurr,没有,我刚刚尝试过,但由于
const
,它失败了。但是没有
const
迭代器它是不可更改的,因为
const
的定义是“无法更改的值/对象”,并且在for循环的赋值时抛出错误,而不是在访问member@gardian06确实如此,如果你想修改一个集合元素,你必须按照MichaelBurr在他的…中所说的做一个元素的副本,从集合中删除原始元素,修改副本并将其重新插入集合
std::less
是默认的compa是的,所以它们实际上不是不同的类型。@DeadMG:发布了更多信息,表明我的暗中刺杀是正确的。(这是暗中刺杀)@DeadMG只有在使用默认参数时才有意义,但我没有,因此编译器抛出了error@gardian06:事实上,你给我们看的代码确实使用了默认参数。我们怎么知道你没有使用默认参数?@MooingDuck:很好的心理调试。
#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();
  }
}
std::set<Board, std::greater<Board>>::iterator 
std::set<Board>::iterator 
std::set<Board, std::less<Board>>::iterator