假设有函数 ovelaodsint
和double
。
void Print(int v)
{
cout << v << endl;
}
void Print(double v)
{
cout << v << endl;
}
有一个函数旨在作为可调用的上述函数之一传入。
template<typename FnT>
void Function(int v, FnT&& fn)
{
fn(v);
}
但以下代码不明确:
Function(1, Print);
编译器无法推导出第二个参数的类型。这很容易解决:
Function(1, static_cast<void(*)(int)>(Print));
我相信存在更通用和优雅的方法来解决这个问题。在 STL 算法中,当添加函数重载时,这个问题会被提出。
vector<int> v = { 1,2,3 };
for_each(v.begin(), v.end(), Print); // ambigous code
如何以漂亮的方式解决这个问题?
将其包装在一个函数对象中:
#include <iostream>
#include <utility>
void Print(int v)
{
std::cout << v << std::endl;
}
void Print(double v)
{
std::cout << v << std::endl;
}
template<typename FnT>
void Function(int v, FnT&& fn)
{
fn(v);
}
auto print_wrapper() {
return [](auto&&...args) -> decltype(auto)
{
return Print(std::forward<decltype(args)>(args)...);
};
}
int main()
{
Function(1, print_wrapper());
}
从理论上讲,我们在这里所做的是使用绷带来修复损坏的设计。
更好的设计是将 的概念定义Print
为模板函数对象。然后我们可以专门化它并根据我们的内心需求定制它。
一个(非常完整的)模型boost::hash<>
值得任何人花半天的时间作为学习练习。
一个简单的例子:
#include <iostream>
#include <utility>
#include <string>
struct Printer
{
void operator()(const int& i) const {
std::cout << i << std::endl;
}
void operator()(const double& i) const {
std::cout << i << std::endl;
}
template<class Anything>
void operator()(const Anything& i) const {
custom_print(i);
}
};
struct Foo
{
};
void custom_print(Foo const& f)
{
std::cout << "a Foo" << std::endl;
}
template<typename X, typename FnT>
void Function(X const& x, FnT&& fn)
{
fn(x);
}
int main()
{
Function(1, Printer());
Function(1.0, Printer());
Function(Foo(), Printer());
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句