我遇到了一些可以通过以下代码恢复的问题:

template <typename Key, typename Data, typename fct>
size_t wrapper(const std::pair<Key, Data> & p)
{
  return fct(p.first);
}

int main(int argc, char *argv[])
{
  size_t val =
    wrapper<int, int, dft_hash_fct<int>>(std::pair<int,int>(5,9));

  return 0;
}


我正在使用clang编译器3.4版,并且此代码无法编译并出现以下错误

test-tmp.C:17:5: error: no matching function for call to 'wrapper'
    wrapper<int, int, dft_hash_fct<int>>(std::pair<int,int>(5,9));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test-tmp.C:9:8: note: candidate template ignored: invalid explicitly-specified argument
      for template parameter 'fct'


想法是将哈希函数(模板参数fct)包装在std::pair上,以便仅获取第一个字段。

dft_hash_fct是另一个模板,定义如下:

template <typename Key>
size_t dft_hash_fct(const Key & key)
{
  return SuperFastHash(key);
}


该通用功能有效;它已在其他情况下使用。

所有这一切的目的是将基于哈希的集合(而不是映射)复用为任何类型的项的键的映射。基于散列的ser在构造时间接收散列函数。

感谢您的评论(David,Andrey和Kazark)

编辑:

好吧,我知道,typename fct是一个类型,因此我不能作为指针函数来处理;对不起,琐事。不幸的是,我认为在包装器中将函数作为参数传递的方法不起作用,因为哈希集需要具有以下签名的函数指针:

size_t (*the_function)(const Key & key);


因此,意识到这一点,由于您的观察,我将相关代码更改为:

template <typename Key, typename Data, size_t (*fct)(const Key & k)>
size_t wrapper(const std::pair<Key, Data> & p)
{
  return (*fct)(p.first);
}

int main(int argc, char *argv[])
{
  size_t val =
    wrapper<int, int, dft_hash_fct<int>>(std::pair<int,int>(5,9));

  return 0;
}


进行编译,链接和运行。另外,我把这一行:

size_t (*fct)(const std::pair<int, int>&) =
    wrapper<int, int, dft_hash_fct<int>>;

cout <<  (*fct)(std::pair<int, int>(4,6)) << endl;


然后编译,链接也运行。因此,我可以说编译器(当然也根据语言)可以实例化函数并处理指向该函数的函数指针。

因此,在那之后,我尝试修改我的原始代码,这是HAshSet的派生类,用于管理由第一个字段散列的对。

我声明为:

template <typename Key, typename Data>
class HashMap : public HashSet<std::pair<Key, Data>>
{
  ...
  HashMap(size_t (*function)(const Key & key))
    : HashSet<Key, Data>(wrapper<Key, Data, function>)
  {

  }

..
};


但是编译(使用std = c ++ 11)失败并显示以下错误

./tpl_dynSetHash.H:353:7: error: no matching constructor for initialization of
      'HashSet<std::pair<unsigned long, long>>'
    : HashSet<std::pair<Key,Data>(
      ^
testDynSetHash.C:178:8: note: in instantiation of member function
      'HashMap<unsigned long, long>::HashMap' requested here
  HMap table;


但是,如果我用以下方式代替对基本构造函数的调用

: HashSet<Key, Data>(wrapper<Key, Data, dft_hash_fct<Key>)


这样编译就可以了。因此,我认为问题在于参数类型声明(但我不知道是什么)。

最佳答案

传递函数的标准习惯用法是将它们作为函数对象传递,例如

template <typename Key, typename Data, typename Fct>
size_t wrapper(const std::pair<Key, Data> & p, Fct fct)
{
  return fct(p.first);
}


然后使用以下命令调用包装器:

int main(int argc, char *argv[])
{
  // no explicit template arguments required
  size_t val =
    wrapper(std::pair<int,int>(5,9), &dft_hash_fct<int>);

  return 0;
}




另一方面,在您的代码中:

template <typename Key, typename Data, typename fct>
size_t wrapper(const std::pair<Key, Data> & p)
{
  return fct(p.first);
}


typename fct为类型引入别名。在此函数内,fct命名一个类型;因此,fct(p.first)创建一个类型为fct的对象,并且需要将该对象转换为size_t才能从wrapper返回它。您也可以使用它,但是必须使用的类型必须如下所示:

struct dft_hash_fct_t
{
    size_t result;
    dft_hash_fct_t(int p) : result(SuperFashHash(p)) {}
    operator size_t() const { return result; }
};


这可能不是您想要的。

关于c++ - c++用作模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18665131/

10-16 04:53