当我使用boost :: unordered_set时,我遇到了一种我没想到的行为。我提取了一个最小的例子(不太确定' minimal'尽管:-))来证明我的意思。该程序执行以下操作:
这个尺寸不是我的预期。我认为第二个实例不会被插入,因为它与第一个实例相同。文档说:
泼尼松: 一个二元谓词,它接受与元素相同类型的两个参数并返回一个bool。表达式pred(a,b),其中pred是这种类型的对象,a和b是键值,如果a被认为等同于b,则返回true。这可以是实现函数调用操作符的类,也可以是指向函数的指针(请参阅构造函数)。默认为equal_to,返回与应用等于运算符(a == b)相同。 unordered_set对象使用此表达式来确定两个元素键是否相等。 unordered_set容器中没有两个元素可以使用此谓词生成true的键。 别名为成员类型unordered_set :: key_equal。
和
插入: 在unordered_set中插入新元素。 只有当元素不等同于容器中已有的任何其他元素时,才会插入每个元素(unordered_set中的元素具有唯一值)。
所以我没有正确阅读规范,但我无法弄清楚出错的地方。 (该规范来自www.cplusplus.com。我对tr1 :: unordered_set,gcc 4.8.1,boost 1.54有相同的经验。[我们还没有使用C ++ 11工作......]) 。我很欣赏任何关于我去哪里的提示。
示例:
/* File: test_set.cpp
Compile: g++ -I ${BOOST_INCLUDE} -L ${BOOST_LIB) -lboost_unit_test_framework test_set.cpp -o test_set
Output:
Running 1 test case...
test_set.cpp(110): error in "types_construction_and_operators": check ec.size() == 1 failed [2 != 1]
*** 1 failure detected in test suite "Master Test Suite"
*/
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/functional.hpp>
#include <boost/unordered_set.hpp>
#include <boost/functional/hash.hpp>
#include <boost/operators.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/results_reporter.hpp>
#include <boost/test/output_test_stream.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/detail/unit_test_parameters.hpp>
#include <boost/test/utils/nullstream.hpp>
typedef boost::onullstream onullstream_type;
using boost::test_tools::output_test_stream;
using namespace boost::unit_test;
#define BOOST_TEST_MODULE test_unordered_set
struct edge_type;
struct edge_equal_to;
typedef boost::unordered_set<edge_type, boost::hash<edge_type>, edge_equal_to > edge_collection_type;
std::size_t hash_value( edge_type const& edge );
struct edge_type : public boost::equality_comparable<edge_type> {
edge_type( std::size_t index, std::size_t f, std::size_t t );
edge_type( edge_type const& );
std::size_t index;
std::size_t from_node_index;
std::size_t to_node_index;
edge_type& operator=( edge_type const& that );
bool operator==( edge_type const& that ) const;
};
struct edge_equal_to : std::binary_function< edge_type, edge_type, bool > {
bool operator()( edge_type const& edge1, edge_type const& edge2 ) const;
};
bool edge_equal_to::operator()( edge_type const& edge1,
edge_type const& edge2 ) const {
return edge1.index == edge2.index ;
}
std::size_t hash_value( edge_type const& edge ) {
std::size_t seed = 0;
boost::hash_combine(seed, edge.index );
boost::hash_combine(seed, edge.from_node_index );
boost::hash_combine(seed, edge.to_node_index );
return seed;
}
edge_type::edge_type( std::size_t idx,
std::size_t f,
std::size_t t ) :
index(idx), from_node_index(f), to_node_index(t) {
}
edge_type::edge_type( edge_type const& that ) {
from_node_index = that.from_node_index;
to_node_index = that.to_node_index;
index = that.index;
}
edge_type& edge_type::operator=( edge_type const& that ) {
if( this != &that ) {
from_node_index = that.from_node_index;
to_node_index = that.to_node_index;
index = that.index;
}
return *this;
}
bool edge_type::operator==( edge_type const& that ) const {
return index == that.index &&
from_node_index == that.from_node_index &&
to_node_index == that.to_node_index;
}
BOOST_AUTO_TEST_SUITE( test_suite_unordered_set )
BOOST_AUTO_TEST_CASE( types_construction_and_operators )
{
edge_type edge1( 1, 100, 101 );
BOOST_CHECK_EQUAL( edge1.index, 1 );
BOOST_CHECK_EQUAL( edge1.to_node_index, 101 );
BOOST_CHECK_EQUAL( edge1.from_node_index, 100 );
edge_type edge2( 1, 102, 103 );
BOOST_CHECK_EQUAL( edge2.index, 1 );
BOOST_CHECK_EQUAL( edge2.to_node_index, 103 );
BOOST_CHECK_EQUAL( edge2.from_node_index, 102 );
BOOST_CHECK( edge1 != edge2 );
edge_collection_type ec;
ec.insert( edge1 );
BOOST_CHECK_EQUAL( ec.size(), 1 );
BOOST_CHECK_EQUAL( ec.key_eq()( edge1, edge2 ), true );
ec.insert( edge2 );
BOOST_CHECK_EQUAL( ec.size(), 1 ); // <---- This test fails !
}
BOOST_AUTO_TEST_SUITE_END()
答案 0 :(得分:1)
如果两个实例应该被认为是相等的,那么它们也应该具有相同的哈希值。仅当两个实体的散列相同时才使用等式谓词,以确定它们是否真正相等或者是偶然哈希冲突的情况。
http://www.boost.org/doc/libs/1_56_0/doc/html/unordered/hash_equality.html
如果您希望使用不同的相等功能,您还需要 使用匹配的哈希函数。例如,实施案例 不敏感的字典,您需要定义不区分大小写的相等 谓词和哈希函数:
答案 1 :(得分:1)
测试失败,因为您已将2个不相等的对象插入到集合中。因此ec.size()应返回2.
这是因为edge_equal的实现仅测试索引的相等性,而哈希函数依赖于所有成员。