将C 方法参数转换为模板参数会因编译错误而失败

Converting C++ method argument to template argument fails with compile error

本文关键字:参数 编译 错误 失败 方法 转换      更新时间:2023-10-16

我正在重构几年前做出的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&);

因此,一般而言:"比较器"是什么,在编译时不知道。实际值在运行时传递。这是汇编错误的基本原因:所有模板参数必须在编译时指定。