请考虑以函数引用作为其第一个参数的函数模板的示例。它基于第一个参数的函数签名被重载。每个重载的主体为其签名提供适当的第一个参数函数。基于函数对象操作符()的“过载”函数模板签名
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;
}
由于过载的,以任一这些功能的参考可以作为第一ARG通过:
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);
那铿锵给出的错误信息是非常明确和匹配你所期望的。
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
我现在没有时间来写一个完整的答案,但你可以使用SFINAE:使用'的std :: enable_if'并创建两个特点:'is_callable_with_T'和'is_callable_with_T_and_vector'。 – Angew 2014-12-05 18:07:48