打开散列c ++时的“不完整类型”
Posted
技术标签:
【中文标题】打开散列c ++时的“不完整类型”【英文标题】:"Incomplete Type" when open hashing c++ 【发布时间】:2014-11-29 20:25:10 【问题描述】:我是 C++ 新手,遇到了一个我以前从未见过的错误。我正在尝试通过使用哈希表(开放哈希)的回溯算法进行搜索。
在进行递归调用之前,我正在搜索哈希表以查看之前是否已搜索过当前位置(并且已失败),然后在递归调用返回时将整数向量“B”插入哈希表false 这样可以避免以后搜索相同的位置。
这是我程序调用文件中的函数以进行哈希处理:
bool open_hash_solve (vector<int> B, vector<Move> & MS, vector<Move> & TMS, OpenHashTable<vector<int>> & H)
if (solved(B))
return true;
vector<Move> curr = currentMoves(B, TMS);
for (int m = 0; m < curr.size(); m++)
vector<int> moveMade = makeMove(B, curr[m]);
if (!H.contains(moveMade))
if (open_hash_solve(moveMade, MS, TMS, H))
MS.insert(MS.begin(), curr[m]);
return true;
else
H.insert(moveMade);
return false;
头文件分离教科书链接:
#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
int nextPrime( int n );
// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x ) --> Insert x
// bool remove( x ) --> Remove x
// bool contains( x ) --> Return true if x is present
// void makeEmpty( ) --> Remove all items
template <typename HashedObj>
class OpenHashTable
public:
explicit OpenHashTable( int size = 101 ) : currentSize 0
theLists.resize( 101 );
bool contains( const HashedObj & x ) const
auto & whichList = theLists[ myhash( x ) ];
return find( begin( whichList ), end( whichList ), x ) != end( whichList );
void makeEmpty( )
for( auto & thisList : theLists )
thisList.clear( );
bool insert( const HashedObj & x )
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList) )
return false;
whichList.push_back( x );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
bool insert( HashedObj && x )
auto & whichList = theLists[ myhash( x ) ];
if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
return false;
whichList.push_back( std::move( x ) );
// Rehash; see Section 5.5
if( ++currentSize > theLists.size( ) )
rehash( );
return true;
bool remove( const HashedObj & x )
auto & whichList = theLists[ myhash( x ) ];
auto itr = find( begin( whichList ), end( whichList ), x );
if( itr == end( whichList ) )
return false;
whichList.erase( itr );
--currentSize;
return true;
private:
vector<list<HashedObj>> theLists; // The array of Lists
int currentSize;
void rehash( )
vector<list<HashedObj>> oldLists = theLists;
// Create new double-sized, empty table
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
theLists.resize( nextPrime( 2 * theLists.size( ) ) );
for( auto & thisList : theLists )
thisList.clear( );
// Copy table over
currentSize = 0;
for( auto & thisList : oldLists )
for( auto & x : thisList )
insert( std::move( x ) );
size_t myhash( const HashedObj & x ) const
static hash<HashedObj> hf; ***** ERROR HERE *****
return hf( x ) % theLists.size( );
;
#endif
我的错误:
SeparateChaining.h: In instantiation of ‘size_t OpenHashTable<HashedObj>::myhash(const HashedObj&) const [with HashedObj = std::vector<int>; size_t = long unsigned int]’:
SeparateChaining.h:33:44: required from ‘bool OpenHashTable<HashedObj>::contains(const HashedObj&) const [with HashedObj = std::vector<int>]’
movetest1.cpp:107:29: required from here
SeparateChaining.h:106:34: error: ‘std::hash<std::vector<int> > hf’ has incomplete type
static hash<HashedObj> hf;
^
我该如何解决这个问题? 如果我的描述没有意义或需要澄清,请告诉我。提前致谢!
【问题讨论】:
你能把调用编译器的那一行(带所有参数)放在一边吗?如果还可以告诉编译器版本... g++ -g -std=c++11 movetest1.cpp @lrleon 显然,编译器不知道类型 hash原因是std::hash
没有为std::vector
定义,std::vector<bool>
除外。它仅为basic types and select library types 定义。您必须实现自己的哈希算法。
关于您的最后一条评论,hash( x )
是无效代码,因为std::hash
是类模板,而不是函数模板。
您也不能为std::hash<std::vector<int>>
编写自己的特化,因为std::vector<int>
不是用户定义的类型。
适当的解决方案是C++ standard library - OpenHashTable
应该允许其用户指定散列算法:
template<typename HashedObj, typename Hash = std::hash<HashedObj>>
class OpenHashTable
// ...
size_t myhash(const HashedObj& x) const
static Hash hf;
return hf(x) % theLists.size();
;
所以你可以这样使用它:
struct my_vector_int_hash
size_t operator()(const std::vector<int>& v) const
// your code here
;
OpenHashTable<std::vector<int>, my_vector_int_hash> hashtable;
更新:只要讨论过你是否可以专攻std::hash<std::vector<int>>
,这就是为什么不允许你这样做。
[namespace.std]/1
说:
除非另有说明,否则如果 C++ 程序将声明或定义添加到命名空间
std
或命名空间 std 内的命名空间,则其行为未定义。只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,程序才能将任何标准库模板的模板特化添加到命名空间std
。
std::vector<int>
不是用户定义的类型,也不依赖于任何用户定义的类型,因此这种特化是非法的,会导致未定义的行为。
【讨论】:
如下所述,您可以专门化 hash<:vector>>。它可能不那么优雅,但你可以。我检查了@Savin @lrleon 这是未定义的行为。 这样吗?模板myhash
的实现应该如何以上是关于打开散列c ++时的“不完整类型”的主要内容,如果未能解决你的问题,请参考以下文章