我有以下代码来制作unordered_set<Interval>
。编译好了。
struct Interval {
unsigned int begin;
unsigned int end;
bool updated; //true if concat. initially false
int patternIndex; //pattern index. valid for single pattern
int proteinIndex; //protein index. for retrieving the pattern
};
struct Hash {
size_t operator()(const Interval &interval);
};
size_t Hash::operator()(const Interval &interval){
string temp = to_string(interval.begin) + to_string(interval.end) + to_string(interval.proteinIndex);
return hash<string>()(temp);
}
unordered_set<Interval, string, Hash> test;
但是,当我尝试使用此代码插入时无法编译:
for(list<Interval>::iterator i = concat.begin(); i != concat.end(); ++i){
test.insert((*i));
}
此外,我无法确定错误消息的问题,例如:
note: candidate is:
note: size_t Hash::operator()(const Interval&)
note: candidate expects 1 argument, 2 provided
我以为我只提供了一个论点......
我的插入代码有什么问题?
这是新的实例化代码:unordered_set<Interval, Hash> test;
但是,我仍然收到大量错误消息,例如:
note: candidate is:
note: size_t Hash::operator()(const Interval&) <near match>
note: no known conversion for implicit ‘this’ parameter from ‘const Hash*’ to ‘Hash*’
答案 0 :(得分:31)
第一个问题:
您正在传递string
作为实例化unordered_set<>
类模板的第二个模板参数。 The second argument should be the type of your hasher functor,std::string
不是可调用对象。
或许打算写:
unordered_set<Interval, /* string */ Hash> test;
// ^^^^^^^^^^^^
// Why this?
另外,我建议使用begin
和end
以外的名称作为(成员)变量,因为它们是C ++标准库的算法名称。
第二个问题:
你应该记住that the hasher function should be qualified as const
,所以你的算子应该是:
struct Hash {
size_t operator() (const Interval &interval) const {
// ^^^^^
// Don't forget this!
string temp = to_string(interval.b) +
to_string(interval.e) +
to_string(interval.proteinIndex);
return (temp.length());
}
};
第三个问题:
最后,如果您希望std::unordered_set
能够使用类型为Interval
的对象,则需要定义与哈希函数一致的相等运算符。默认情况下,如果您未指定任何类型参数作为std::unordered_set
类模板的第三个参数,则将使用operator ==
。
您的班级operator ==
目前没有Interval
的任何超载,因此您应该提供一个。{1}}。例如:
inline bool operator == (Interval const& lhs, Interval const& rhs)
{
return (lhs.b == rhs.b) &&
(lhs.e == rhs.e) &&
(lhs.proteinIndex == rhs.proteinIndex);
}
<强>结论:强>
完成上述所有修改后,您可以在此live example中看到您的代码。
答案 1 :(得分:0)
我认为,Andy Prowl与您的代码完美结合fixed the problems。但是,我将以下成员函数添加到您的Interval
中,该函数描述了使两个间隔相同的原因:
std::string getID() const { return std::to_string(b) + " " + std::to_string(e) + " " + std::to_string(proteinIndex); }
请注意,我还遵循了Andy Prowl的建议,将成员begin
重命名为b
,并将成员end
重命名为e
。接下来,您可以使用lambda expressions轻松定义哈希和比较函数。因此,您可以如下定义unordered_set
:
auto hash = [](const Interval& i){ return std::hash<std::string>()(i.getID()); };
auto equal = [](const Interval& i1, const Interval& i2){ return i1.getID() == i2.getID(); };
std::unordered_set<Interval, decltype(hash), decltype(equal)> test(8, hash, equal);
最后,出于可读性考虑,我将您的for
循环转换为基于范围的for
循环:
std::list<Interval> concat {{1, 2, false, 3, 4}, {2, 3, false, 4, 5}, {1, 2, true, 7, 4}};
for (auto const &i : concat)
test.insert(i);
for (auto const &i : test)
std::cout << i.b << ", " << i.e << ", " << i.updated << std::endl;
输出(我刚打印了每个Interval
的前三个成员):
2、3、0
1,2,0
如您所见,仅打印了两个间隔。未将第三个({1, 2, true, 7, 4}
)插入concat
,因为它的b
,e
和proteinIndex
等于第一个间隔({ {1}}。