【问题标题】:How can I pass a function name and variable list of arguments to a function in C++?如何将函数名称和变量参数列表传递给 C++ 中的函数?
【发布时间】:2022-09-30 14:38:22
【问题描述】:

在 Python 中,您可以将函数名称和参数列表传递给外部函数,该函数调用内部函数并将这些参数传递给它,如下所示:

Passing functions with arguments to another function in Python?:

def perform(fun, *args):
    fun(*args)

def action1(args):
    # something

def action2(args):
    # something

perform(action1)
perform(action2, p)
perform(action3, p, r)

我如何在 C++ 中做到这一点?

    标签: c++ variadic-templates variadic parameter-pack


    【解决方案1】:

    虽然您可以在 C 和 C++ 中使用 variadic functions with va_list, va_start(), va_arg(), and va_end() 执行此操作,但在 C++ 中使用 variadic templates (parameter packs) 来执行此操作要干净得多。

    秘诀是允许通过typename FuncType 传入任何格式的通用函数,并允许通过typename... FuncArgs 传入参数的可变参数列表。因此,模板说明符将是template<typename FuncType, typename... FuncArgs>。然后将函数名称作为FuncType innerFunc 传递给外部函数,并将可变参数列表作为FuncArgs... args 传递给外部函数。在模板函数内部,参数列表可以作为args... 传递给子函数,如下所示:innerFunc(args...);

    这是上下文中的全部内容:

    // INNER FUNCTIONS TO PASS TO AN OUTER FUNCTION
    
    void print1(int i)
    {
        printf("print1: %i\n", i);
    }
    
    void print2(double d, int i)
    {
        printf("print2: %f, %i\n", d, i);
    }
    
    void print3(int i, double d, const std::string& str)
    {
        printf("print3: %i, %f, %s\n", i, d, str.c_str());
    }
    
    
    // OUTER FUNCTION
    
    template<typename FuncType, typename... FuncArgs>
    void OuterFunc(FuncType innerFunc, FuncArgs... args)
    {
        printf("OuterFunc start.\n");
    
        // Call the inner function with all passed-in args!
        printf("Calling inner function with all passed-in args.\n");
        innerFunc(args...);
    
        printf("OuterFunc end.\n\n");
    }
    
    int main()
    {
        OuterFunc(print1, 100);
        OuterFunc(print2, 99.1234, 77);
        OuterFunc(print3, 123, 10.55, "hey you!");
    
        return 0;
    }
    

    完整的、可运行的示例,带有 cmets:

    variadic_templates_parameter_packs_and_functions.cpp 来自我的 eRCaGuy_hello_world 回购:

    // C++ includes
    #include <cstdint>  // For `uint8_t`, `int8_t`, etc.
    #include <cstdio>   // For `printf()`
    #include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.
    #include <string>
    
    
    // -------------------- Some inner functions to choose from START -------------------
    
    void print1(int i)
    {
        printf("print1: %i\n", i);
    }
    
    void print2(double d, int i)
    {
        printf("print2: %f, %i\n", d, i);
    }
    
    void print3(int i, double d, const std::string& str)
    {
        printf("print3: %i, %f, %s\n", i, d, str.c_str());
    }
    
    // -------------------- Some inner functions to choose from END ---------------------
    
    // The outer function, which is a variadic template, containing one `typename...` parameter pack.
    // See: https://en.cppreference.com/w/cpp/language/parameter_pack
    template<typename FuncType, typename... FuncArgs>
    void OuterFunc(FuncType innerFunc, FuncArgs... args)
    {
        printf("OuterFunc start.\n");
    
        // Call the inner function with all passed-in args!
        printf("Calling inner function with all passed-in args.\n");
        // See the "Expansion loci" section of this documentation here:
        // https://en.cppreference.com/w/cpp/language/parameter_pack
        // This is really cool, because calling the inner function like this is **just like the Python
        // example here!**: https://*.com/a/803632/4561887--except you pass the arguments
        // to the inner function as `args...` in C++ here instead of as `*args` (the contents of the
        // arguments list) in Python.
        innerFunc(args...);
    
        printf("OuterFunc end.\n\n");
    }
    
    // int main(int argc, char *argv[])  // alternative prototype
    int main()
    {
        printf("Demonstrate variadic templates (parameter packs) in C++!\n\n");
    
        OuterFunc(print1, 100);
        OuterFunc(print2, 99.1234, 77);
        OuterFunc(print3, 123, 10.55, "hey you!");
    
        return 0;
    }
    

    示例构建和运行命令,以及输出:

    eRCaGuy_hello_world/cpp$ time g++ -Wall -Wextra -Werror -O3 -std=c++17 variadic_templates_parameter_packs_and_functions.cpp -o bin/a && bin/a
    
    real    0m0.281s
    user    0m0.245s
    sys 0m0.036s
    Demonstrate variadic templates (parameter packs) in C++!
    
    OuterFunc start.
    Calling inner function with all passed-in args.
    print1: 100
    OuterFunc end.
    
    OuterFunc start.
    Calling inner function with all passed-in args.
    print2: 99.123400, 77
    OuterFunc end.
    
    OuterFunc start.
    Calling inner function with all passed-in args.
    print3: 123, 10.550000, hey you!
    OuterFunc end.
    

    【讨论】:

      最近更新 更多