为什么clang会拒绝gcc接受的这个unordered_set定义?

Hin*_*sum 4 c++ hash compilation clang unordered-set

我希望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;
}
Run Code Online (Sandbox Code Playgroud)

我试图编译它,而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);
        ^
Run Code Online (Sandbox Code Playgroud)

我在这里没有得到错误信息,你能告诉我如何修复我的代码吗?

小智 8

尽管Baum mit Augen已经告诉过你这个问题,但我认为最好还解释一下如何从错误信息中找出更多信息.

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::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, std::__1::equal_to, std::__1::allocator >::__rehash' requested here
        __rehash(__n);
        ^

第一部分告诉您将a const node与另一个进行比较时出错const node.在这一点上,你需要自己判断,以确定你是否应该能够比较两个const nodes.

答案是肯定的.此时,您可以简化代码以取消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;
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试编译它,clang将为您提供更多详细信息:

error: invalid operands to binary expression ('const node' and 'const node')
        a == b;
        ~ ^  ~
note: candidate function not viable: 'this' argument has type 'const node', but method is not marked const
        bool operator == (const node& n){return value == n.value;}
             ^

"方法没有标记为const"告诉你究竟是什么问题.要修复它,就像Baum mit Augen的回答一样,标记方法const.

另一方面,如果答案是"不,你不应该能够比较两个const node对象",那么问题就是"为什么要unordered_set比较两个const node对象以及如何阻止它".为此,初始编译器消息的其余部分将告诉您哪些部分导致该比较.你必须从上到下,在每一步都搞清楚"这应该有效吗?" 如果是的话,弄清楚它为什么不起作用.如果不是,请找出导致尝试的原因.


Bau*_*gen 5

您的比较运算符必须是const合格的:

bool operator == (const node& n) const {return value == n.value;}
                                 ^^^^^
Run Code Online (Sandbox Code Playgroud)

通过将操作符实现为非成员函数,可以很容易地避免这样的错误.请参阅运算符重载的基本规则和习惯用法是什么?了解更多信息和最佳实践.