虽然您可以在 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.