Это похоже на Вывести значение параметра шаблона из концепции, но я не могу найти работающее решение на основе ответа.
Я создал предикат для использования с find_if
:
template <class Array>
class c_str_array_eq {
static_assert(std::predicate<c_str_array_eq, const Array &>);
const char *str;
public:
explicit constexpr c_str_array_eq(const char *str) : str{str} {}
bool operator()(const Array &array) const {
return std::strncmp(str, array.data(), array.size()) != 0;
}
};
Целью этого предиката является поиск в коллекции std::array
(или объектов, подобных массиву) строки в стиле c.
Однако при попытке использовать этот предикат я получаю что-то вроде этого:
struct my_object {
std::array<char, 256> str;
}
std::ranges::find_if (a_collection, c_str_array_eq<std::array<char, 256>>("foo"), &my_object::str);
Как я могу заставить компилятор вывести параметр шаблона в c_str_array_eq
в этой ситуации?
шаблонировать оператор, а не класс?
Предикаты обычно не шаблонны. Вместо этого их оператор вызова является шаблонным, поскольку именно оператор вызова инициирует выведение аргументов при вызове алгоритмами стандартной библиотеки.
#include <cstring>
#include <array>
#include <vector>
class c_str_array_eq {
const char *str;
public:
explicit constexpr c_str_array_eq(const char *str) : str{str} {}
template <class Array>
requires requires (const Array& array)
{
array.data();
array.size();
std::strncmp(str, array.data(), array.size());
}
bool operator()(const Array &array) const {
return std::strncmp(str, array.data(), array.size()) != 0;
}
};
struct my_object {
std::array<char, 256> str;
};
int main()
{
std::vector<my_object> a_collection;
std::ranges::find_if (a_collection, c_str_array_eq("foo"), &my_object::str);
}
Это делается почти всеми предикатами стандартной библиотеки, такими как std::less, где шаблон void
по умолчанию будет иметь шаблон operator()
, который выполняет фактический вывод в месте вызова.
«Это делается почти во всех стандартных библиотеках». На самом деле std::less<Object>
сравнивает Object
, тогда как std::less<void>
имеет шаблон operator ()
.
В этом столько смысла, для меня это явно была долгая неделя! Спасибо, что нашли время ответить
Нужно просто убрать
static_assert
.