Преобразование аргумента метода C ++ в аргумент шаблона завершается с ошибкой компиляции - PullRequest
0 голосов
/ 09 марта 2019

Я занимаюсь рефакторингом 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 Ответ

2 голосов
/ 09 марта 2019

Фундаментальным свойством шаблонов C ++ является то, что все параметры шаблона должны быть разрешены во время компиляции .То есть каждый параметр шаблона должен быть известен во время компиляции.Строка с ошибкой компиляции:

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

Но этот comparator является параметром этой функции:

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

Поэтому, вообще говоря, что это за "компаратор",не известно во время компиляции. Фактическое значение передается во время выполнения. Это основная причина вашей ошибки компиляции: все параметры шаблона должны быть указаны во время компиляции. Проще говоря, этот общий подход, который здесь используется, просто не будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...