如何使模板函数成为另一个模板函数的参数?

Tre*_*key 1 c++ parameters templates c++11 std-function

我有一个包含各种算法的类:

class Algorithm{

Algorithm()=delete;

public:
    template <typename IntegerType> 
    static IntegerType One(IntegerType a, IntegerType b);

    template <typename IntegerType> 
    static IntegerType Two(IntegerType a, IntegerType b);

    template <typename IntegerType> 
    static IntegerType Three(IntegerType a, IntegerType b);

    // ...
};
Run Code Online (Sandbox Code Playgroud)

它们可以通过以下方式调用:

int main(){

    Algorithm::One(35,68);
    Algorithm::Two(2344,65);
    //...
}
Run Code Online (Sandbox Code Playgroud)

现在我想创建一个函数,它将采用任何"算法"函数,并在调用该函数之前和之后执行相同的步骤.
这是我有的:

template <typename IntegerType>
void Run_Algorithm(std::function<IntegerType(IntegerType,IntegerType)>fun, IntegerType a, IntegerType b){
    //... stuff ...
    fun(a,b);
    //... stuff ...
    return;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试像这样调用函数时:

Run_Algorithm(Algorithm::One,1,1);
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

cannot resolve overloaded function ‘One’ based on conversion to type ‘std::function<int(int, int)>’
Run Code Online (Sandbox Code Playgroud)

如何设置通用例程,将所需算法作为参数?

编辑:
此解决方案按预期工作.它看起来像这样:

template <typename IntegerType>
void Run_Algorithm(IntegerType(*fun)(IntegerType, IntegerType), IntegerType a, IntegerType b){
    //... stuff ...
    fun(a,b);
    //... stuff ...
    return;
}
Run Code Online (Sandbox Code Playgroud)

dyp*_*dyp 5

函数模板Algorithm::One的名称就像这里的一组重载函数的名称一样.要从该集合中选择一个重载,您需要将该名称放在需要特定函数类型(签名)的上下文中.这是不可能的std::function,因为它可以在其ctor中采取任何参数(具有一些"可调用"要求).

此外,std::function如果函数是模板,则不需要使用作为参数类型,并且无用.它只会添加一个不必要的类型擦除和一个间接级别.传递函数的标准习语是:

template <typename Fun, typename IntegerType>
void Run_Algorithm(Fun fun, IntegerType a, IntegerType b);
Run Code Online (Sandbox Code Playgroud)

但这并不能帮助您选择过载集的一个重载.您可以在呼叫站点选择过载,如DieterLücking所 建议的那样,然后使用此成语.

但是,您可以提供过载/或者:

template < typename IntegerType >
void Run_Algorithm(IntegerType(*)(IntegerType, IntegerType),
                   IntegerType, IntegerType);
Run Code Online (Sandbox Code Playgroud)

如果可能的话,它更专业,因此更受欢迎.这里,函数类型是严格的IntegerType(IntegerType, IntegerType),因此编译器可以选择重载集的重载(来自名称Algorithm::One).

注意:根据[temp.deduct.type]/5,IntegerType在参数的非推导上下文中的第一个参数中Algorithm::One.因此,第二个和第三个参数用于推断IntegerType.扣除后,功能类型已完全指定,可以选择过载.

问题仍然存在1)如果这是你想要的,2)如果有更好的方法来做你想做的事情.