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

标签 c++ c++11 variadic-templates std-function callable

我正在学习 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。

最佳答案

我猜你有点把可变参数模板部分和一些设计缺陷混在一起了

让我们开始吧。

序言:处理可变模板的正确方法是使用rvalue-referencestd::forward来实现 perfect forwarding .

1) 简单的方法:你根本不需要上课

您实际上并没有指代任何成员,因此类只会带来复杂性。这些情况最好引用一个免费的功能

#include <functional>
#include <iostream>

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

template<typename Func, typename... Args>
double var_finder(double c, Func&& f, Args&&... args) {
    return c * std::forward<Func>(f)(std::forward<Args>(args)...);
};

int main () {
    std::cout << var_finder(0.1, finder, 2, 0) << std::endl;

    return 0;
}

Demo 1

您的函数接受 2 个参数,因此您必须将零作为第二个参数传递。

2) 使用类

您尝试的问题是您想使用 c_test 本身的函数调用 c_test.var_finder。现在你必须弄清楚你想要什么样的设计。你可以做出2个假设。首先是“我无论如何都想要我的类中的查找器函数”,然后你必须将它设为 static 因为它真的不使用类成员所以你不需要 c_test< 的实例,对吧?所以使用自由函数或静态成员函数会留下 var_finder 实现,你只需要这样调用它

#include <functional>
#include <iostream>

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


        template<typename Func, typename... Args>
        double var_finder(double c, Func&& f, Args&&... args) {
            return c * std::forward<Func>(f)(std::forward<Args>(args)...);
        };
};

int main () {
    c_test test;

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

    return 0;
}

Demo 2

您可以做的第二个假设是“不,我希望使用 var_finder 调用任何函数成员,无论它来自哪里”。我强烈反对这种方法,因为它是从糟糕的设计中提取解决方案,因此我建议重新考虑您的设计以落入解决方案 1 或 2。

3) 奖励:一个不错的设计

您可以添加一个非可变参数函数并将用法委托(delegate)给 lambda 的使用,这允许您在其中使用成员函数而无需定义可变参数模板来处理它(这是标准库函数)。

#include <functional>
#include <iostream>

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

template<typename Func, typename... Args>
double var_finder(double c, Func&& f, Args&&... args) {
    return c * std::forward<Func>(f)(std::forward<Args>(args)...);
};

template<typename Func, typename... Args>
double var_finder(double c, Func&& f) {
    return c * std::forward<Func>(f)();
};

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

int main () {
    double a = 2.0;
    double b = 0.0;

    // use as usual
    std::cout << var_finder(0.1, finder, a, b) << std::endl;

    // use with lambda
    std::cout << var_finder(0.1, [a,b](){ return a+b; }) << std::endl;

    // lambda with member argument, less gruesome than a variadic template calling a member function
    c_test c;
    std::cout << var_finder(0.1, [a,b, &c](){ return c.finder(a,b); }) << std::endl;

    return 0;
}

Bonus Demo

关于C++11 可变参数模板在类中调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62211078/

相关文章:

c++ - 从 wstring 中删除某些字符

c++ - 使 "cout << obj1 + obj2 << endl;"工作

c++ - OpenMP 卸载到 Nvidia 错误减少

c++ - 为集合中的每个元素调用带有多个参数的函数

c++ - 对于单个参数,可变参数形式与非可变参数形式不明确

c++ - Qt SQL : how to differentiate between a double and an int?

c++ - istreambuf_iterator 什么时候抛出异常?

c++ - 具有模板参数取决于参数列表

c++ - 添加两个整数的可变参数模板列表

c++ - 整数模板参数和子函数调用