为什么clang拒绝这个unordered_set定义,而gcc接受?

4

我希望使用自己的哈希函数测试 unordered_set

#include<unordered_set>
#include<iostream>
#include<functional>
using namespace std;
struct node{
    size_t value;
    bool operator == (const node& n){return value == n.value;}
};
size_t h(const node& n){
    return n.value;
}
int main(){
    unordered_set<node, std::function<size_t(const node&)>> s2(3,h);//failed
    return 0;
}

我试图编译它,但clang报了大量错误:

clang++ m.cpp -std=c++11
In file included from m.cpp:1:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/unordered_set:324:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:659:21: error: invalid operands to binary
    expression ('const node' and 'const node')
        {return __x == __y;}
                ~~~ ^  ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__hash_table:2175:32: note: in instantiation of member
    function 'std::__1::equal_to<node>::operator()' requested here
                            key_eq()(__cp->__value_, __np->__next_->__value_);
                            ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__hash_table:2121:9: note: in instantiation of member function
    'std::__1::__hash_table<node, std::__1::function<unsigned long (const node &)>, std::__1::equal_to<node>, std::__1::allocator<node> >::__rehash' requested here
        __rehash(__n);
        ^

我不太理解这里的错误信息,你可以帮我解决代码问题吗?
2个回答

8
虽然Baum mit Augen已经告诉你问题所在,但我认为解释一下如何从错误信息中获取更多信息是一个好主意。
使用以下命令编译:clang++ m.cpp -std=c++11
在文件m.cpp中,第1行: 
在文件/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/unordered_set:324中: 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:659:21: 错误: 无效的二进制操作符表达式 ('const node' and 'const node')
        {return __x == __y;}
                ~~~ ^  ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__hash_table:2175:32: 注意: 请求此处的成员函数'std::__1::equal_to::operator()'
                            key_eq()(__cp->__value_, __np->__next_->__value_);
                            ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__hash_table:2121:9: 注意: 请求此处的成员函数'std::__1::__hash_table, std::__1::equal_to, std::__1::allocator >::__rehash'
        __rehash(__n);
        ^
这部分首先告诉你,存在将一个const node与另一个const node进行比较的错误。这时,你需要自己判断是否应该能够比较两个const node
答案是肯定的。此时,你可以简化你的代码,将unordered_set排除在外,并让编译器为你提供更多有关问题的信息。
#include<cstddef>
using namespace std;
struct node{
    size_t value;
    bool operator == (const node& n){return value == n.value;}
};
int main(){
    const node a{}, b{};
    a == b;
}

如果您尝试编译此代码,clang将会给出更多细节:

错误:无效的二元表达式操作数(“const node”和“const node”)
        a == b;
        ~ ^  ~
注释:候选函数不可行:“this”参数具有类型“const node”,但该方法未标记为const
        bool operator == (const node& n){return value == n.value;}
             ^

“方法未标记为const”告诉您问题所在。要解决此问题,如Baum mit Augen的答案所述,将该方法标记为const

另一方面,如果答案是“不,您不能比较两个const node对象”,那么问题就是“为什么unordered_set正在比较两个const node对象,我怎样才能阻止它”。对于这个问题,初始编译器消息的其余部分将告诉您哪些部分导致了此比较。您需要从上到下进行,每一步找出“这应该可以工作吗?”如果可以,请找出为什么没有工作。如果不能,请找出导致尝试的原因。


5

你的比较运算符必须被标记为const

bool operator == (const node& n) const {return value == n.value;}
                                 ^^^^^

通过将运算符实现为非成员函数,可以轻松避免这样的错误。更多信息和最佳实践,请参见运算符重载的基本规则和惯用法是什么?


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