函数模板特化的别名

Alias to a function template specialization

int f1(int a, int b) { return a+b; }
int f2(int a, int b) { return a*b; }

template <typename F> void foo(int i, int j)
{
 // do some processing before
 F(i,j);  
 // do some processing after 
}

我想像这样为 foo 的特化创建别名:

constexpr auto foo1 = &foo<f1>;
constexpr auto foo2 = &foo<f2>;

并像这样调用函数:foo1(1,2);foo2(1,2); 有什么办法可以在 C++ 中实现这一点?谢谢!


编辑: foo() 不是 f1 的包装器,它是调用 f1 或 f2 的函数。我需要在通话前后做一些额外的事情。 F 是一个仿函数,我想要一个 'short cut' 到 foo 的特化。 上面的代码是一种伪代码。

评论中有一些好的方法:std::bind,使用lambda,将F的实例传递给函数,所以我会提供一个替代方案。

如果您将传递给 foo 的函数类型将始终为 int(int, int),那么您将模板参数设为非类型模板参数,然后使用您的其中一个实例化它函数:

int f1(int a, int b) { std::cout<<"f1\n"; return a+b; }
int f2(int a, int b) { std::cout<<"f2\n"; return a*b; }

template <int(*F)(int, int)> 
void foo(int i, int j)
{
    F(i,j);   
}

然后这样称呼它:

int main()
{
    constexpr auto foo1 = foo<f1>;
    constexpr auto foo2 = foo<f2>;
    foo1(1,2);
    foo2(1,2);
}

输出:

f1
f2

我们在这里做的技巧是我们让模板参数成为对函数的引用,这很老套但据我所知是合法的。

Demo

is spot-on for the OP's request. To complement that answer: an alternative method could be letting the int(int, int) function pointer be an additional argument to the function (in which case we needn't use template techniques), and use std::bind设置要使用的不同默认大小写函数。

#include <iostream>
#include <functional>

int f1(int a, int b) { return a+b; }
int f2(int a, int b) { return a*b; }
int f3(int a, int b) { return a-b; }

void foo(int i, int j, int (*f)(int, int)) {
  // do some processing before
  std::cout << f(i, j) << std::endl;
  // do some processing after
}

int main()
{
  const auto foo1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, &f1);
  const auto foo2 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, &f2);

  foo1(5, 5);     // 10
  foo2(5, 5);     // 25
  foo(5, 5, &f3); // 0

  return 0;
}

上述的变体可以允许使用函数包装器 (std::function) 将帮助函数存储为值,以防由于某种原因,这些函数可能会在调用者对象之前超出范围 ( foo1, foo2, ...).

void foo(int i, int j, const std::function<int(int, int)> f) { /* ... */ }

// ...

const auto foo1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, f1);
const auto foo2 = std::bind(foo, std::placeholders::_1, std::placeholders::_2, f2);