我在类中定义了一个枚举类型,我想创建这些对象的unordered_set作为类的成员:
#include <unordered_set>
class Foo {
public:
enum Bar {
SOME_VALUE
};
// Error: implicit instantiation of std::hash
std::unordered_set<Bar> getValues() const {
return _values;
}
private:
std::unordered_set<Bar> _values;
};
现在,我知道明显的答案是向unordered_set添加自定义哈希函数:
std::unordered_set<Bar, BarHasher>
然而,我想知道的是,是否有一种方法可以为bar枚举专门化std :: hash,以便任何使用unordered_map的人自动获得散列行为。
这适用于所有其他数据类型,但不适用于枚举 - 因为枚举不能向前声明。
为了使其工作,我必须在枚举定义之后放置std :: hash的定义,但在第一次使用之前,这意味着我必须将它放在类主体的中间,这是行不通的。
答案 0 :(得分:3)
一种可能性是将枚举放入基类中。不幸的是,您必须为每个枚举成员提供使用声明。一种方法是使用范围枚举( <?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
/* Select queries return a resultset */
if ($result = $mysqli->query("SELECT wie, waar, metwie, voeruig FROM data")) {
printf("Select returned %d rows.\n", $result->num_rows);
while ($row = mysql_fetch_array($result)) {
switch ($row) {
case "wie":
echo "<select name='wie'>";
echo "<option value='" . $row['wie'] . "'>" . $row['wie'] . "</option>";
echo "</select>";
break;
case "waar":
echo "<select name='waar'>";
echo "<option value='" . $row['waar'] . "'>" . $row['waar'] . "</option>";
echo "</select>";
break;
case "metwie":
echo "<select name='metwie'>";
echo "<option value='" . $row['metwie'] . "'>" . $row['metwie'] . "</option>";
echo "</select>";
break;
}
case "voeruig":
echo "<select name='voeruig'>";
echo "<option value='" . $row['voeruig'] . "'>" . $row['voeruig'] . "</option>";
echo "</select>";
break;
}
/* free result set */
$result->close();
}
?>
),这需要使用enum class Bar
而不是Foo::Bar::SOME_VALUE
。这样做,您只需要Foo::SOME_VALUE
。
using FooBase::Bar;
答案 1 :(得分:3)
然而,我想知道的是,是否有一种方法可以为bar枚举专门化std :: hash,以便使用unordered_map的任何人自动获得散列行为。
没有奇迹,所以任何人只有在专业化之后才会使用专门的std::hash
。由于您无法在另一个类中专门化类并且您的枚举嵌套,因此在类中使用std::hash
会有问题。正如你指出的枚举不能向前宣布。因此,在类中使用专门的std::hash
是唯一的解决方案(不创建基类或&#34;取消&#34;枚举):通过引用聚合/声明并在std::hash
专门化后使用外部。
#include <iostream>
#include <unordered_set>
#include <memory>
struct A {
enum E {
first, second
};
A();
std::unique_ptr< std::unordered_set<E> > s_; //!< Here is
};
namespace std {
template<>
class hash<A::E> {
public:
std::size_t operator()(A::E const& key) const noexcept {
std::cout << "hash< A::E >::operator()" << std::endl;
return key;
}
};
}
A::A()
: s_(new std::unordered_set<E>)
{ }
int main(void) {
A a;
a.s_->insert(A::first);
std::unordered_set< A::E > s;
s.insert(A::second);
}
打印
散列&LT; A :: E&gt; :: operator()
散列&LT; A :: E&gt; :: operator()
因此,在课程A
之外,每个人都可以将A::E
与std::hash
以及内部课程一起使用,我们也会将A::E
与std::hash
一起使用。另外,如果您不想通过引用汇总std::unordered_set
,则可以仅为内部使用实现自定义哈希(然后转发std::hash
个调用。)
答案 2 :(得分:1)
您似乎已经覆盖了问题中的所有角度。
我无法想办法做到这一点。
总结一下,你只能改变这种情况的事实:
enum
非嵌套(将其放入封闭的命名空间中)或