請考慮以函數引用作爲其第一個參數的函數模板的示例。它基於第一個參數的函數簽名被重載。每個重載的主體爲其簽名提供適當的第一個參數函數。基於函數對象操作符()的「過載」函數模板簽名
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