C++11 &引用;“不完整类型”;当打开散列c++; 我对C++有了新的认识,我得到了一个我以前从未见过的错误。我试图通过使用哈希表(开放哈希)的回溯算法进行搜索

C++11 &引用;“不完整类型”;当打开散列c++; 我对C++有了新的认识,我得到了一个我以前从未见过的错误。我试图通过使用哈希表(开放哈希)的回溯算法进行搜索,c++11,recursion,hash,hashtable,backtracking,C++11,Recursion,Hash,Hashtable,Backtracking,在进行递归调用之前,我正在搜索哈希表,以查看当前位置之前是否已搜索过(并且已失败),然后在递归调用返回false时将int“B”的向量插入哈希表中,以便避免以后对同一位置的搜索 下面是我的程序中调用散列文件的函数: bool open_hash_solve (vector<int> B, vector<Move> & MS, vector<Move> & TMS, OpenHashTable<vector<int>> &

在进行递归调用之前,我正在搜索哈希表,以查看当前位置之前是否已搜索过(并且已失败),然后在递归调用返回false时将int“B”的向量插入哈希表中,以便避免以后对同一位置的搜索

下面是我的程序中调用散列文件的函数:

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;
}
bool open\u hash\u solve(向量B、向量和MS、向量和TMS、OpenHashTable和H){
如果(已解决(B))
返回true;
矢量电流=电流移动(B,TMS);
对于(int m=0;m
头文件与教科书分开链接:

#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
\ifndef单独链接
#定义单独的链接
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int nextPrime(int n);
//分离哈希表类
//
//构造:近似初始大小或默认值为101
//
//**********************公共业务*********************
//布尔插入(x)-->插入x
//bool删除(x)-->删除x
//bool包含(x)-->如果存在x,则返回true
//void makeEmpty()-->删除所有项目
样板
类OpenHashTable
{
公众:
显式OpenHashTable(int size=101):currentSize{0}
{theLists.resize(101);}
布尔包含(常量HashedObj&x)常量
{
auto&whichList=theLists[myhash(x)];
返回find(开始(whichList),结束(whichList),x)!=end(whichList);
}
void makeEmpty()
{
用于(自动和此列表:列表)
thisList.clear();
}
布尔插入(常量HashedObj&x)
{
auto&whichList=theLists[myhash(x)];
如果(查找(开始(whichList),结束(whichList),x)!=end(whichList))
返回false;
whichList.push_back(x);
//重新灰化;见第5.5节
如果(++currentSize>theList.size())
再灰化();
返回true;
} 
布尔插入(HashedObj&&x)
{
auto&whichList=theLists[myhash(x)];
如果(查找(开始(whichList),结束(whichList),x)!=end(whichList))
返回false;
whichList.push_back(标准::move(x));
//重新灰化;见第5.5节
如果(++currentSize>theList.size())
再灰化();
返回true;
}
bool remove(常量HashedObj&x)
{
auto&whichList=theLists[myhash(x)];
自动itr=查找(开始(whichList)、结束(whichList)、x);
如果(itr==结束(whichList))
返回false;
whichList.erase(itr);
--电流大小;
返回true;
}
私人:
向量列表;//列表的数组
int-currentSize;
无效再灰分()
{
向量oldLists=theLists;
//创建新的双尺寸空表
调整列表大小(nexttime(2*theLists.size());
用于(自动和此列表:列表)
thisList.clear();
调整列表大小(nexttime(2*theLists.size());
用于(自动和此列表:列表)
thisList.clear();
//把表格抄过来
currentSize=0;
用于(自动和此列表:旧列表)
用于(自动和x:此列表)
插入(标准::移动(x));
}
大小\u t myhash(常量HashedObj&x)常量
{
静态哈希hf;****此处有错误*****
返回hf(x)%t列表大小();
}
};
#恩迪夫
我的错误:

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;
                        ^
SeparateChaining.h:在“size\u t OpenHashTable::myhash(const HashedObj&)const[with HashedObj=std::vector;size\u t=long unsigned int]”的实例化中:
SeparateChaining.h:33:44:bool OpenHashTable::contains(const HashedObj&)const[with HashedObj=std::vector]中必需的
movetest1.cpp:107:29:从此处开始需要
SeparateChaining.h:106:34:错误:“std::hash hf”的类型不完整
静态hash-hf;
^
我该如何解决这个问题??
如果我的描述不合理或需要澄清,请告诉我。提前谢谢

原因是除了
std::vector
之外,没有为
std::vector
定义
std::hash
。它的定义仅适用于。您必须实现自己的哈希算法

关于您的最后一条评论,
hash(x)
是无效代码,因为
std::hash
是类模板,而不是函数模板

您也不能为
std::hash
编写自己的专门化,因为
std::vector
不是用户定义的类型

适当的解决方案应采用-
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();
    }
};
模板
类OpenHashTable{
// ...
大小\u t myhash(常量HashedObj&x)常量{
静态Hash-hf;
返回hf(x)%t列表大小();
}
};
因此,您可以按如下方式使用它:

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;
struct my\u vector\u int\u hash{
size_t运算符()(const std::vector&v)const{
//你的代码在这里
}
};
开放哈希表;

更新:只要讨论了您是否可以专门化
std::hash
,下面就是为什么不允许您这样做的原因

[namespace.std]/1
说:

<> > C++程序的行为是未定义的,除非它在命名空间<代码> STD<代码>或命名空间内的命名空间中添加声明或定义,除非另有说明。仅当声明取决于用户定义的类型且专门化满足原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板专门化添加到命名空间
std

std::vector
不是用户定义的类型,也不是dep