我不希望函数指针开销,我只想为具有相同签名的两个不同函数使用相同的代码:
void f(int x);
void g(int x);
...
template<typename F>
void do_work()
{
int v = calculate();
F(v);
}
...
do_work<f>();
do_work<g>();
这可能吗?
清除可能的混淆:“模板参数”是指模板的参数/参数和 不 a函数参数,其类型是模板化的。
答案 0 :(得分:22)
你的想法没问题,但是你没有传递一个类型而是一个值(具体来说,一个函数指针&gt;。或者,传递一个提供函数的模板策略 - 阅读Andrei Alexandrescu的现代C ++设计是一个好主意。< / p>
#include <iostream>
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
template<F f>
int do_work()
{
return f(7);
}
int main()
{
std::cout << do_work<f>() << '\n'
<< do_work<g>() << '\n';
}
OR
int calculate() { return 4; }
struct F { int do_something_with(int x) { return 2 * x; } };
struct G { int do_something_with(int x) { return -3 * x; } };
// or, make these functions static and use Operator::do_something_with() below...
template<typename Operation>
int do_work()
{
int v = calculate(7);
return Operation().do_something_with(v);
}
int main()
{
std::cout << do_work<F>() << '\n'
<< do_work<G>() << '\n';
}
答案 1 :(得分:9)
您可以将函数指针作为模板参数,但函数对象更多是“C ++ ish”。但是,您可以以接受两种变体的方式编写函数模板:
#include <iostream>
void f(int x)
{
std::cout << "inside function f\n";
}
struct g
{
void operator()(int x)
{
std::cout << "inside function object g\n";
}
};
template <typename Functor>
void do_work(Functor fun)
{
fun(42);
}
int main()
{
// template argument is automatically deduced
do_work(&f);
// but we could also specify it explicitly
do_work<void(*)(int)>(&f);
// template argument is automatically deduced
do_work(g());
// but we could also specify it explicitly
do_work<g>(g());
}
此处,名称Functor
提示可以通过f(x)
语法调用的任何类型。函数自然支持这种语法,对于函数对象,f(x)
是f.operator()(x)
的语法糖。
答案 2 :(得分:9)
一种非常有可能生成直接函数调用的方法,因为它给编译器没有选项,就是使用静态成员函数:
struct F { static void func(int x) { /*whatever*/ } };
struct G { static void func(int x) { /*whatever*/ } };
template<class T>
void do_work() {
T::func(calculate());
}
没有函数指针,没有临时函数,也没有不必要的this
。当然,我什么都不保证,但即使禁用了优化,生成的代码也应该合理。
答案 3 :(得分:6)
不,您需要将函数包装在包含operator()
的包装类中。这是一个例子:
class Functor_f
{
public:
void operator()(int x)
{
}
};
class Functor_g
{
public:
void operator()(int x)
{
}
};
template<typename F>
void do_work()
{
F f;
int v = calculate();
f(v);
}
int main()
{
do_work<Functor_f>();
do_work<Functor_g>();
}
您可以使用std::ptr_fun
自动为您执行此包装。例如:
void f(int x)
{
}
void g(int x)
{
}
template<typename F>
void do_work(F f)
{
int v = calculate();
f(v);
}
int main()
{
do_work(std::ptr_fun(f));
do_work(std::ptr_fun(g));
}