[C ++ 11可变参数模板在类中调用函数

问题描述 投票:2回答:3

我正在用C ++ 11学习可变参数模板。如何调用test.finder作为test.var_finder的功能参数?

#include <functional>
#include <iostream>

class c_test {
    public:

        double finder(double a, double b = 0) {
            return a + b;
        };


        template<typename... Args>
        double var_finder(double c, Args... args, std::function<double (Args... args)> func) {
            return c * func(args...);
        };
};

int main () {
    c_test test;

    std::cout << test.var_finder(0.1, 2, test.finder) << std::endl;

    return 0;
}

我的预期结果是0.1 *(2 + 0)= 0.2。

c++ c++11 variadic-templates
3个回答
0
投票

这里有很多事情要处理。

首先,将参数包args放在最后,否则编译器将不知道从何处停止匹配参数(除非您指定模板参数)。

template<typename... Args>
double var_finder(double c, std::function<double (Args... args)> func, Args... args)

第二,不要在std::function中命名参数;也只是不使用std::function,而是使用函数指针。

template<typename... Args>
double var_finder(double c, double (*func)(Args...), Args... args)

第三,将finder设为静态,否则会遇到成员函数指针,并且语法更难掌握。

static double finder(double a, double b = 0)

第三,为finder提供可选参数。否则,无法推导出参数包,因为它与funcargs都不匹配。

std::cout << test.var_finder(0.1, c_test::finder, 2.0, 0.0) << std::endl;

这将为您提供以下内容。

class c_test {
public:
    static double finder(double a, double b = 0) {
        return a + b;
    }

    template<typename... Args>
    double var_finder(double c, double (*func)(Args...), Args... args) {
        return c * func(args...);
    }
};

int main () {
    c_test test;

    std::cout << test.var_finder(0.1, c_test::finder, 2.0, 0.0) << std::endl;
}

Demo


0
投票

您的解决方案有很多问题:

1]您不能将成员函数转换为std::function,因为没有对象就无法调用成员函数。您可以通过使成员函数为static或使用std::bind或使用lambda来解决此问题。

2)在方法参数中间不能有可变参数列表。可变参数必须转到参数列表的末尾。

3)您不能在参数列表本身内部“动态”推断模板参数。解决方案:将新的模板参数与默认模板参数一起使用。

4)我看不出要在std :: function中使用的函数带有默认参数的机会,该函数会返回不同的签名double(double)double(double,double)

class c_test {
    public:

        static double finders(double a, double b = 0) {
            return a + b;
        };

        double finder(double a, double b = 0) {
            return a + b;
        };


        template<typename... Args, typename F= std::function<double(Args...)> >
            double var_finder(double c, F func, Args... args) {
                return c * func(args...);
            }
};

int main () {
    c_test test;

    // use static member
    std::cout << test.var_finder(0.1, test.finders,  2.,3.) << std::endl;

    // use lambda instead of all the hacky things
    std::cout << test.var_finder(0.1, [&test](double p1,double p2){ return test.finder(p1,p2); },  2.,3.) << std::endl;

    return 0;
}

-1
投票

我发现使用lambdas的可能性:

std::cout << test.var_finder<c_test, double> (0.1, test, 2, [] (c_test test_, double a_) { return test_.finder(a_); } ) << std::endl;

还有其他(不太麻烦的)可能性吗?

© www.soinside.com 2019 - 2024. All rights reserved.