C++ 是否可以在C+;中使用函数(-name)作为模板参数+;?
我不需要函数指针开销,我只需要为两个具有相同签名的不同函数提供相同的代码:C++ 是否可以在C+;中使用函数(-name)作为模板参数+;?,c++,templates,function,C++,Templates,Function,我不需要函数指针开销,我只需要为两个具有相同签名的不同函数提供相同的代码: 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>(); void f(int x); 无效g(int x); ... 模板 无效工作 { int v=计算();
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>();
void f(int x);
无效g(int x);
...
模板
无效工作
{
int v=计算();
F(v);
}
...
你工作吗;
你工作吗;
这可能吗
为了消除可能的混淆:对于“模板参数”,我指的是模板的参数/参数,不是类型为模板的函数参数。可以将函数指针作为模板参数,但函数对象更像是“C++”。但是,您可以以接受两种变体的方式编写函数模板:
#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());
}
#包括
空f(整数x)
{
std::cout否,您需要使用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>();
}
你的想法不错,但你不是传递一个类型,而是一个值(具体地说,是函数指针)。或者,通过一个提供函数的模板策略——Andrei Alexandrescu阅读现代C++设计是个好主意。
#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';
}
#包括
intf(intx){返回2*x;}
int g(int x){return-3*x;}
类型定义int(*F)(int);
模板
int do_work()
{
返回f(7);
}
int main()
{
std::cout一种极有可能生成直接函数调用的方法是使用静态成员函数,因为它不给编译器任何选项:
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());
}
struct F{static void func(int x){/*whatever*/};
结构G{static void func(int x){/*whatever*/};
模板
无效工作{
T::func(calculate());
}
没有函数指针,没有临时变量,也没有不必要的这
。当然,我不保证什么,但生成的代码应该是合理的,即使禁用了优化功能。+1…并且它们编译为直接调用,在运行时没有函数指针调用开销。@Doug:这不保证。但是很可能,因为e> std::sort
从该优化中受益匪浅。您在那里的实现将typename Fun
参数与函数原型void(*)(int)相匹配
,然后对两个调用使用相同的实例化-而不是内联:这就是为什么您最终将函数指针作为运行时参数传递给do\u work(有趣)
+1-不值得-1:但它可以很好地接受函数对象;这是灵活的标准使用方法。@mAlters-绝对不能保证。我稍微误读了FredOverflow的答案-我认为FredOverflow已经接受了一个模板非类型函数指针参数,正如问题所示,ra而不是模板类型参数。非类型参数更可能编译为直接调用。+1用于显示带有fn指针的合理解决方案。但我认为,与do_work_f()和do_work_g()的复制粘贴版本相比,这仍然会带来一些运行时开销…?@Martin:这是一个至关重要的问题-所有这些都是乐观主义者的问题。我不会打赌这是内联的,而我会打赌一个策略模板成员…@Tony-你能不能链接一些资源,以(大约)描述一个模板策略的事情,就像你在这个问题上采用它一样?返回操作(7);
应该是返回操作()(7)
@Martin:我对上面的模板策略版本做了一些修改,以更直接地反映这个问题。虽然有点冗长,但我倾向于对策略提供的内容使用函数名——每个策略中有多个函数是很常见的,这通常会使代码更易于理解。;@Stephane Rolland:对于一个更大的具体应用,请考虑<代码> STD::排序接受一个小于策略的……通过不硬编码操作程序。第一个例子(没有<代码> STD::pTrfFix)提供了更好的实际内联的机会(当然,它依赖于很多)。因此最有可能是最快的,可能有点违反直觉。干杯,+1:非常好的解决方案。不适用于支持我问题的问题,但作为一般解决方案非常好!
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';
}
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());
}