我正在重构我几年前制作的API,该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 ++技能变得越来越生锈...
答案 0 :(得分:2)
C ++模板的基本属性是必须在编译时 解析所有模板参数。也就是说,必须在编译时知道每个模板参数。出现编译错误的行:
return hashTable->contains(mapEntry,
compareMapValue<KEY, VALUE, comparator>);
但是这个comparator
是此函数的参数:
bool containsValue(const VALUE& value,
int (*comparator)(const VALUE&, const VALUE&);
因此,通常来说:“比较器”在编译时未知。实际值在运行时传递。这是编译错误的根本原因:所有模板参数都必须在编译时指定简而言之,这里使用的这种总体方法根本行不通。