基于 C++98 中函数对象运算符 () 签名的“重载”函数模板

“Overload” function template based on function object operator() signature in C++98

本文关键字:重载 函数模板 C++98 函数 对象 运算符 基于      更新时间:2023-10-16

我想创建一个模板函数,该函数接受一个函数和一个向量,并使用该函数将该向量映射到函数模板将返回的另一个向量。

如果作为参数的函数是自由函数,则它可能具有两个签名之一。

// 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 结构以同时处理函数对象和自由函数,要么需要使用重载来分别路由函数对象和自由函数。

http://coliru.stacked-crooked.com/a/1471088cbc3b8544

这是我的方法:

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 模式。