是否可以在C++中将函数(-name)作为模板参数?

Mar*_* Ba 15 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>();
Run Code Online (Sandbox Code Playgroud)

这可能吗?


清除可能的混淆:"模板参数"是指模板的参数/参数,不是模板类型的函数参数.

Ton*_*roy 23

你的想法没问题,但你不是传递一个类型而是一个值(特别是一个函数指针>.或者,传递一个提供函数的模板策略 - 阅读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'; 
}
Run Code Online (Sandbox Code Playgroud)

要么

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'; 
}
Run Code Online (Sandbox Code Playgroud)

  • `return Operation(7);`应该是`return Operation()(7);` (2认同)

fre*_*low 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());
}
Run Code Online (Sandbox Code Playgroud)

这里,名称Functor提示任何可通过f(x)语法调用的类型.函数自然支持这种语法,对于函数对象,函数f(x)是语法糖f.operator()(x).


小智 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());
}
Run Code Online (Sandbox Code Playgroud)

没有函数指针,没有临时工,没有必要this.当然,我什么都不保证,但即使禁用了优化,生成的代码也应该合理.


Nav*_*een 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>();

}
Run Code Online (Sandbox Code Playgroud)

您可以使用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));

}
Run Code Online (Sandbox Code Playgroud)