【问题标题】:Using a templated function as template parameter使用模板函数作为模板参数
【发布时间】:2018-03-02 02:55:43
【问题描述】:

我正在编写一个具有重复调用函数的类,并决定将其实现为将函数作为模板参数。 作为我正在谈论的具体示例,请考虑以下类:

#include <array>

template<double (*func)(std::array<double,3>)>
class MyClass
{

public:
    MyClass()
    {
        std::array<double,3> v {{0.1,0.2,0.1}};
        func(v);
    }
};

然后可以用函数实例化,例如:

double func(std::array<double,3> x)
{
    return x[0]*x[0]+x[1];
}

int main()
{
    MyClass<func> entity;
}

但是,我需要函数可以用不同的类型调用(函数中的操作当然适用于所有类型),即我希望将这个函数模板化,如下所示:

template<typename scalartype, typename vectype>
scalartype func1(vectype x)
{
    scalartype res = x[0]*x[0]+x[1];
    return res;
}

我仍然可以使用它作为模板参数,但是函数参数和返回类型在类中是固定的。那么我怎样才能在类中使用作为模板函数的函数呢?例如,我可以用四个整数的std::vector 调用它并返回一个整数。

我尝试使用模板模板参数,但我什至不知道如何将两个模板参数与它们一起使用(因为它们似乎只允许模板...语法)。如果表述不清楚,对不起,我还是新手。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    您可以将模板函数放入一个类中,然后将该类传递给MyClass

    #include <iostream>
    #include <vector>
    #include <array>
    
    struct templateHolder {
        template <typename vectype, typename scalartype = typename vectype::value_type>
        static scalartype func(vectype x) {
            return x[0] + x[1];
        }
    };
    
    template<typename T>
    class MyClass
    {
    
    public:
        MyClass()
        {
            std::vector<int> vec {1,2};
            std::cout << T::func(vec) << std::endl;
    
            std::array<double, 2> arr {0.5, 3.33};
            std::cout << T::func(arr) << std::endl;
        }
    };
    
    int main() {
        MyClass<templateHolder> foo;
        return 0;
    }
    

    我选择从vectype 推导出scalartype。不一定是您想要的,但根据您的用例,它可能是一种选择。

    【讨论】:

    • 这很酷。你知道这是否会以某种方式影响性能(与作为模板参数的非模板函数相比)?
    • @bernhard_e 不应该。编译器可以推断出在编译时要调用哪个版本的func,因此两种情况下的结果都是函数调用,仅此而已。如果您不需要修改它,那么这两种情况下的一项性能改进是传递 const vectype&amp; 而不是按值传递。