将C 方法参数转换为模板参数会因编译错误而失败
Converting C++ method argument to template argument fails with compile error
我正在重构几年前做出的API,它带来了共同数据结构的多态性实现(列表,地图,集合,树,树,图),可在http上获得://www.data-types.com。对于需要值比较的结构(例如:哈希表),我让它们使用C比较器,并且一切都很好。
在下一个版本中,我正在尝试升级比例比较器的行为,以便在可以推断出一个用户时不需要创建一个行为。一切都很好,直到我尝试将方法参数转换为模板参数。示例代码减少到裸骨:
#include <iostream>
#include <cstddef>
#include <stdexcept>
template<typename VALUE>
class HashTable {
public:
HashTable(int (*comparator)(const VALUE&,const VALUE&), std::size_t (*hasher)(const VALUE&)){
std::cout << "HashTable constructor called" << std::endl;
}
bool contains(const VALUE& value, int (*customCompare)(const VALUE&,const VALUE&)) const{
return false;
}
~HashTable(){
std::cout << "HashTable destructor called" << std::endl;
}
};
template<typename _KEY, typename _VALUE>
struct MapEntry {
_KEY key;
_VALUE value;
};
template<typename KEY, typename VALUE, int (*comparator)(const KEY&, const KEY&)>
static inline int compareMapKey(const MapEntry<KEY,VALUE>& left, const MapEntry<KEY,VALUE>& right) {
return comparator(left.key, right.key);
}
template<typename KEY, typename VALUE, int (*comparator)(const VALUE&, const VALUE&)>
static inline int compareMapValue(const MapEntry<KEY,VALUE>& left, const MapEntry<KEY,VALUE>& right) {
return comparator(left.value, right.value);
}
template<typename KEY, typename VALUE, std::size_t (*hash)(const KEY&)>
static inline std::size_t hashMapKey(const MapEntry<KEY, VALUE>& element) {
return hash(element.key);
}
template<typename KEY, typename VALUE, int (*compareByKey)(const KEY&, const KEY&), std::size_t (*hashByKey)(const KEY&)>
class HashMap {
public:
HashMap(){
hashTable = new HashTable<MapEntry<KEY,VALUE>>(compareMapKey<KEY, VALUE, compareByKey>, hashMapKey<KEY, VALUE, hashByKey>);
std::cout << "HashMap constructor called" << std::endl;
}
bool containsValue(const VALUE& value, int (*comparator)(const VALUE&, const VALUE&)) const{
MapEntry<KEY,VALUE> mapEntry;
mapEntry.value = value;
return hashTable->contains(mapEntry, compareMapValue<KEY, VALUE, comparator>);
}
~HashMap(){
delete hashTable;
std::cout << "HashMap destructor called" << std::endl;
}
private:
HashTable<MapEntry<KEY,VALUE>>* hashTable;
};
static inline int comparator(const long& left, const long& right) {
if(left<right) return -1;
else if (left>right) return 1;
else return 0;
}
static inline std::size_t hash(const long& item) {
return item;
}
int main() {
long val = 1;
HashMap<long, long, comparator, hash> map;
map.containsValue(val, comparator);
std::cout << "!!!Hello World!!!" << std::endl;
return 0;
}
这拒绝编译,给我这个错误:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Test.d" -MT"src/Test.o" -o "src/Test.o" "../src/Test.cpp"
../src/Test.cpp: In instantiation of ‘bool HashMap<KEY, VALUE, compareByKey, hashByKey>::containsValue(const VALUE&, int (*)(const VALUE&, const VALUE&)) const [with KEY = long int; VALUE = long int; int (* compareByKey)(const KEY&, const KEY&) = comparator; std::size_t (* hashByKey)(const KEY&) = hash]’:
../src/Test.cpp:78:35: required from here
../src/Test.cpp:53:79: error: no matching function for call to ‘HashTable<MapEntry<long int, long int> >::contains(MapEntry<long int, long int>&, <unresolved overloaded function type>)’ return hashTable->contains(mapEntry, compareMapValue<KEY, VALUE, comparator>);
../src/Test.cpp:12:7: note: candidate: bool HashTable<VALUE>::contains(const VALUE&, int (*)(const VALUE&, const VALUE&)) const [with VALUE = MapEntry<long int, long int>] bool contains(const VALUE& value, int (*customCompare)(const VALUE&,const VALUE&)) const{
../src/Test.cpp:12:7: note: no known conversion for argument 2 from ‘<unresolved overloaded function type>’ to ‘int (*)(const MapEntry<long int, long int>&, const MapEntry<long int, long int>&)’
有人知道上述解决方案吗?我的C 技能已经变得更加生锈,因为我不再习惯用这种语言工作...
C 模板的基本属性是,必须在编译时间 上解析所有模板参数。也就是说,每个模板参数必须在编译时已知。汇编错误的行:
return hashTable->contains(mapEntry,
compareMapValue<KEY, VALUE, comparator>);
但是此comparator
是此功能的参数:
bool containsValue(const VALUE& value,
int (*comparator)(const VALUE&, const VALUE&);
因此,一般而言:"比较器"是什么,在编译时不知道。实际值在运行时传递。这是汇编错误的基本原因:所有模板参数必须在编译时指定。
相关文章:
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- C++模板-基于参数编译成员函数
- 无法使用模板参数编译提升元状态机
- lambda 和映射,引用参数 - 编译错误
- 为什么在函数参数编译中没有标识符的const关键字
- 无法使用模板参数编译类
- 数组作为函数参数 - 编译错误
- 使用 "using declaration" 扩展非类型模板参数包(模板可变参数编译时 SignalSlot 实现)
- 在 gcc 中使用数组参数编译外部"c"代码
- 为什么对齐的参数编译正确,但在运行时崩溃
- GCC上的亚型参考参数编译错误
- 是否可以将addr2line与使用发布优化参数编译的应用程序一起使用
- 尝试使用可变参数编译代码时出错
- C++ 线程获取引用参数编译失败
- 使用额外的模板参数编译函数
- 使用静态模板函数的默认参数编译错误
- 函数模板参数编译错误
- 谷歌模拟成员函数中的std::pair参数编译失败
- 模板模板参数-编译错误
- 防止基于模板参数编译函数(或部分函数)