#c #templates #functor
#c #шаблоны #функтор
Вопрос:
Я пытаюсь определить функцию, которая позволяет нам вызывать стандартную хэш-функцию или какую-либо пользовательскую функцию и возвращать значение hash .
Вот пример использования моей функции:
auto res = myfunc<std::hash>(2); //hash the integer 2 with the function std::hash
auto res2 = myfunc<std::hash>("abc"); // hash the string "abc" with the function std::hash
auto res3 = myfunc<customHasher>(2); // hash the integer 2 with some custom hash function
Я попытался закодировать, как показано ниже:
template<void (*T)(U)>
size_t myfunc(const U amp;u)
{
return T<U>(u);
}
T
должен быть указатель на функцию, a std::function
или лямбда, и U
является типом параметра T
.
Но она не может быть скомпилирована.
main.cpp:14:23: error: expected ‘>’ before ‘(’ token
template<void (*T)(U)>
^
main.cpp:15:25: error: ‘U’ does not name a type
size_t myfunc(const U amp;u)
^
main.cpp: In function ‘size_t myfunc(const intamp;)’:
main.cpp:17:18: error: ‘U’ was not declared in this scope
return T<U>(u);
Ну, я знаю, что template<void (*T)(U)>
это должно быть неправильно, потому U
что не определено. Но я не знаю, как это исправить.
Комментарии:
1.
std::hash
не является функцией. Исправление вашей попытки указателя на функцию (при условии, что это возможно) все равно не продвинет вас намного дальше.2. @StoryTeller-UnslanderMonica ХОРОШО, я добавил одну строку в свой пост: «T должен быть указателем на функцию, std::function или лямбда, а U — тип параметра T.».
3. это
customhasher
шаблон?return T<U>(u);
предполагает, чтоT
это шаблон, это необходимо или вы могли бы передать, напримерstd::hash<int>
?4. @largest_prime_is_463035818 Да, customhasher похож
std::hash
на шаблон с одним параметром.5. @largest_prime_is_463035818 В этом и суть. Видите ли, я не хочу передавать
std::hash<int>
, я просто хочу просто передатьstd::hash
.
Ответ №1:
Вам нужно объявить оба параметра. Более того, std::hash
это шаблон класса, а не функция. Вы можете использовать параметр шаблона шаблона:
#include <cstdint>
#include <functional>
#include <iostream>
#include <string>
template<typename T, template<typename> typename H = std::hash>
std::size_t myfunc(const T amp;t)
{
return H<T>{}(t);
}
int main() {
std::cout << myfunc(std::string{"123"});
}
Хотя, чтобы использовать то же самое с вашим customHasher
, он также должен быть шаблоном класса (with operator()
).
Обратите внимание, что вам нужно явно сконструировать строку в main
, иначе T
не может быть выведено, чтобы быть std::string
.
Комментарии:
1. Круто, не знал этого. В C 17 есть это?
2. У @kabaus c 98 было это 😉
3. @Yves нет, потому что «abc» — это строковый литерал c, для которого нет специализации std::hash. вам нужно будет указать строку
4. @Yves Я не мастер шаблонов, но вы могли бы использовать перегрузку или специализацию, например, ссылку . Редактировать: забыл, что частичная специализация шаблона не допускается для шаблонов функций. Перегрузка, похоже, работает.
5. @Yves обратите внимание, что преобразование из c-string в std::string не является бесплатным. Вы могли бы изучить возможность использования
std::hash<std::string_view>
, который поддерживает несколько строковых форматов (но НЕ является владельцем)