Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以在C+;中使用函数(-name)作为模板参数+;?_C++_Templates_Function - Fatal编程技术网

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());
}