Шаблон функции "перегрузки" на основе сигнатуры оператора функционального объекта () в C++98
Я хочу сделать шаблонную функцию, которая принимает функцию и вектор и использует функцию для сопоставления этого вектора с другим вектором, который будет возвращен шаблоном функции.
Если функция, взятая в качестве аргумента, является свободной функцией, она может иметь одну из двух сигнатур.
// T is the parameter of the function template
T sig1(const T x);
T sig2(const T x, const std::vector<T>& v);
Это также может быть функциональный объект, в котором operator()
будет вести себя как свободные функции. Использование шаблона функции для любой из 4 возможностей должно быть прозрачным.
std::vector<int> v;
// ... fill v somehow ...
// foo is either free function or function object instance
const std::vector<int> a = map_vec(foo, v);
Я спросил, как это сделать для C++11, и получил отличный ответ от 0x499602D2.
Шаблон функции "Перегрузка" на основе сигнатуры оператора функционального объекта ()
Ответ 0x499602D2 основан на том факте, что это две разные сигнатуры шаблонов в C++11:
template<typename F, typename T>
auto map_vec(F&& fnc, const std::vector<T>& source)
-> decltype(void(fnc(std::declval<T>())), std::vector<T>{});
template<typename F, typename T>
auto map_vec(F&& fnc, const std::vector<T>& source)
-> decltype(void(fnc(std::declval<T>(), source)), std::vector<T>{});
Я также хотел бы знать, как решить эту проблему в C++98.
Вот мои усилия до сих пор. У меня есть структура SFINAE, которая может определить, принимает ли объект функции два аргумента. Я не знаю, как заставить это работать как для функциональных объектов, так и для свободных функций. Либо мне нужно изменить структуру SFINAE для работы как с функциональными объектами, так и со свободными функциями, либо мне нужно использовать перегрузку для маршрутизации функциональных объектов и свободных функций по отдельности.
1 ответ
Вот мой подход:
template <std::size_t, typename T = void> struct ignore_value {typedef T type;};
template <typename T>
T& declval();
template<typename F, typename T>
typename ignore_value<sizeof(declval<F>()(declval<T const>())),
std::vector<T> >::type map_vec(F fnc, const std::vector<T>& source);
template<typename F, typename T>
typename ignore_value<sizeof(declval<F>()
(declval<T const>(), declval<const std::vector<T> >())),
std::vector<T> >::type map_vec(F fnc, const std::vector<T>& source);
Он работает с той же демонстрацией, что и 0x499602D2, с GCC и Clang в режиме C++98.