简体   繁体   English

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

[英]How can I make a template function an argument to another template function?

I have a class that holds various algorithms: 我有一个包含各种算法的类:

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

    // ...
};

They can be called the following way: 可以通过以下方式调用它们:

int main(){

    Algorithm::One(35,68);
    Algorithm::Two(2344,65);
    //...
}

Now I want to make a function that will take any "Algorithm" function and perform the same steps before and after calling that function. 现在,我想制作一个函数,该函数将使用任何“算法”函数,并在调用该函数之前和之后执行相同的步骤。
Here is what I have: 这是我所拥有的:

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

When I try to call the function like this: 当我尝试像这样调用函数时:

Run_Algorithm(Algorithm::One,1,1);

The error I get is: 我得到的错误是:

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

How can I go about setting up a generic routine, that takes the desired algorithm as a parameter? 如何设置以所需算法作为参数的通用例程?

EDIT: 编辑:
This solution worked as desired. 该解决方案按需工作。 It looks like this: 看起来像这样:

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

The name of a function template, like Algorithm::One , is treated like the name of a set of overloaded functions here. 函数模板的名称(例如Algorithm::One )在这里被视为一组重载函数的名称。 To select one of the overloads from that set, you need to put that name in a context where a specific function type (signature) is required. 要从该集合中选择一个重载,您需要将该名称放在需要特定功能类型 (签名)的上下文中。 This is not possible with std::function , as it can take any argument in its ctor (with some "callable" requirements). 这对于std::function是不可能的,因为它可以在其ctor中接受任何参数(具有一些“可调用”的要求)。

Additionally, using std::function as a parameter type is not required and not useful if the function is a template. 另外,不需要使用std::function作为参数类型,如果该函数是模板,则没有用。 It would just add an unnecessary type erasure and a level of indirection. 这只会增加不必要的类型擦除和间接级别。 The standard idiom of passing functions is: 传递函数的标准用法是:

template <typename Fun, typename IntegerType>
void Run_Algorithm(Fun fun, IntegerType a, IntegerType b);

But this doesn't help you selecting one overload of the overload set. 但这并不能帮助您从过载集中选择一个过载。 You could select the overload at call site, as Dieter Lücking suggested , and then use this idiom. 您可以按照DieterLücking的 建议在呼叫站点选择重载,然后使用此惯用语。

However, you can provide an overload/alternatively: 但是,您可以提供重载/或者:

template < typename IntegerType >
void Run_Algorithm(IntegerType(*)(IntegerType, IntegerType),
                   IntegerType, IntegerType);

which is more specialized and therefore preferred, if possible. 如果可能的话,它更专业,因此是首选。 Here, the function type is strictly IntegerType(IntegerType, IntegerType) , therefore the compiler can select an overload of the overload set (from the name Algorithm::One ). 在这里,函数类型严格是IntegerType(IntegerType, IntegerType) ,因此编译器可以选择重载集的重载(从名称Algorithm::One )。

Note: As per [temp.deduct.type]/5, IntegerType is in the first parameter in a non-deduced context for the argument Algorithm::One . 注意:根据[temp.deduct.type] / 5, IntegerType是在对自变量的非推导出上下文中的第一个参数Algorithm::One Therefore, the second and third parameter are used to deduce IntegerType . 因此,第二个和第三个参数用于推导IntegerType After this deduction, the function type is fully specified and the overload can be selected. 推断之后,将完全指定功能类型并可以选择过载。

The questions remain 1) if that's what you want and 2) if there's a better way to do what you intent to do. 问题仍然存在:1)这是否是您想要的; 2)是否有更好的方法来完成您的意图。

You need Algorithm::One< int > (not Algorithm::One) and thanks to ymett ( Why can't my C++ compiler deduce template argument for boost function? ): 您需要Algorithm :: One <int>(不是Algorithm :: One),并感谢ymett( 为什么我的C ++编译器不能为boost函数推断出模板参数? ):

template <class T> struct identity { typedef T type; };

template <typename IntegerType>
void Run_Algorithm(
    typename identity<
        std::function<IntegerType(IntegerType,IntegerType)>>::type fun,
    IntegerType a,
    IntegerType b)
{
}

int main() {
    Run_Algorithm(Algorithm::One<int>,1,1);
    return 0;
}

You want something like: 您想要类似的东西:

template <template <typename T> class IntegerType>
void Run_Algorithm // ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM