将C ++方法参数转换为模板参数失败,并出现编译错误

时间:2019-03-09 16:04:18

标签: c++ templates

我正在重构我几年前制作的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 ++技能变得越来越生锈...

1 个答案:

答案 0 :(得分:2)

C ++模板的基本属性是必须在编译时 解析所有模板参数。也就是说,必须在编译时知道每个模板参数。出现编译错误的行:

return hashTable->contains(mapEntry,
                           compareMapValue<KEY, VALUE, comparator>);

但是这个comparator是此函数的参数:

bool containsValue(const VALUE& value,
                   int (*comparator)(const VALUE&, const VALUE&);

因此,通常来说:“比较器”在编译时未知。实际值在运行时传递。这是编译错误的根本原因:所有模板参数都必须在编译时指定简而言之,这里使用的这种总体方法根本行不通。