gpt4 book ai didi

c++ - "Overload"基于函数对象operator()签名的函数模板

转载 作者:行者123 更新时间:2023-11-30 00:49:46 25 4
gpt4 key购买 nike

考虑这个将函数引用作为第一个参数的函数模板示例。它根据第一个参数的函数签名进行重载。每个重载的主体为其签名适本地提供第一个参数函数。

template<typename T>
struct MapTtoT { typedef T (type)(const T); };

template<typename T>
std::vector<T> map_vec(
const typename MapTtoT<T>::type& fnc,
const std::vector<T>& source)
{
std::vector<T> dest;
dest.reserve(source.size());
for (const auto i : source)
{
dest.emplace_back(fnc(i));
}
return dest;
}

template<typename T>
struct MapTandVectoT { typedef T (type)(const T, const std::vector<T>&); };

template<typename T>
std::vector<T> map_vec(
const typename MapTandVectoT<T>::type& fnc,
const std::vector<T>& source)
{
std::vector<T> dest;
dest.reserve(source.size());
for (const auto i : source)
{
dest.emplace_back(fnc(i, source));
}
return dest;
}

由于重载,对这些函数中的任何一个的引用都可以作为第一个参数传递:

int foo(const int x);
int bar(const int x, const std::vector<int>& v);

这样做是透明的:

const auto a = map_vec(foo, v);
const auto b = map_vec(bar, v);

上面使用的重载策略不适用于函数对象,因为对象本身没有签名。假设感兴趣的函数对象如下。

class AddNum
{
public:
AddNum(const int num) : num_(num) {}

int operator()(const int x) const
{
return x + num_;
}

private:
const int num_;
};

class AddNumMulSize
{
public:
AddNumMulSize(const int num) : num_(num) {}

int operator()(const int x, const std::vector<int>& v) const
{
return (x + num_) * v.size();
}

private:
const int num_;
};

如何根据调用方式更改函数模板以接受函数对象和函数以及重载?

具体来说,我希望编译:

const AddNum add2(2);
const auto c = map_vec(add2, v);

const AddNumMulSize add2mulsz(2);
const auto d = map_vec(add2mulsz, v);

clang 给出的错误消息非常清楚,符合您的预期。

error: no matching function for call to 'map_vec'

candidate function [with T = int] not viable: no known conversion from 'const AddNum' to 'typename MapTtoT::type &' (aka 'int (&)(const int)') for 1st argument

更新:本题的C++98版本

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

最佳答案

将您的签名更改为一般采用 F 类型的函数对象,然后您可以使用 expression-SFINAE 根据 F 可以调用的内容来限制重载:

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>{});

Demo

关于c++ - "Overload"基于函数对象operator()签名的函数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27321959/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com