如何创建带函数类型声明的模板函数指针列表?
Hey there! Great question—yes, this is totally feasible in C++. The issue you're hitting with typedef is likely due to how C++ handles template-based type aliases before C11, but we can fix this cleanly with modern C features. Let's walk through the solution step by step.
Why Your typedef Isn't Working
In C++03 and earlier, you can't directly define a template typedef—the language doesn't allow it. If you tried something like:
template<typename T> typedef void (*FuncPtr)(T); // Invalid in C++03, still clunky in later versions
That would throw a compiler error because typedef can't be templated directly. Instead, we use alias templates with using (introduced in C++11), which are far more intuitive and flexible.
Step 1: Define a Template Function Pointer Alias
First, create a template alias for your function pointer type. Let's say you want pointers to functions that take a single argument of type T and return void—here's how to write it:
#include <vector> #include <iostream> // Template alias for function pointers: takes T, returns void template<typename T> using FuncPtr = void(*)(T);
If you prefer to first define the underlying function type (then take its pointer), you can do this too:
// First define the function type itself template<typename T> using FuncType = void(T); // Then alias the pointer to that function type template<typename T> using FuncPtr = FuncType<T>*;
Both approaches work—pick whichever reads clearer to you.
Step 2: Create Your List of Function Pointers
Now you can use this alias to declare a container (like std::vector) of templated function pointers. Let's add some example functions and populate the list:
// Example functions matching the FuncPtr signature void printInt(int value) { std::cout << "Integer: " << value << "\n"; } void printDouble(double value) { std::cout << "Double: " << value << "\n"; } void printString(const std::string& value) { std::cout << "String: " << value << "\n"; } int main() { // List of function pointers for int arguments std::vector<FuncPtr<int>> intFunctionList; intFunctionList.push_back(printInt); // List for double arguments std::vector<FuncPtr<double>> doubleFunctionList; doubleFunctionList.push_back(printDouble); // List for string arguments std::vector<FuncPtr<const std::string&>> stringFunctionList; stringFunctionList.push_back(printString); // Test calling the functions for (auto func : intFunctionList) { func(42); } for (auto func : doubleFunctionList) { func(3.14159); } for (auto func : stringFunctionList) { func("Hello, Function Pointers!"); } return 0; }
Step 3: Extend to Generic Function Signatures
If you need function pointers with different return types or variable argument counts, you can make the alias even more flexible with variadic templates:
// Generic function pointer alias: any return type, any number of arguments template<typename ReturnType, typename... Args> using GenericFuncPtr = ReturnType(*)(Args...);
Now you can create lists for functions like int add(int, int):
int add(int a, int b) { return a + b; } int main() { std::vector<GenericFuncPtr<int, int, int>> arithmeticFunctions; arithmeticFunctions.push_back(add); // Call and print the result std::cout << "3 + 5 = " << arithmeticFunctions[0](3,5) << "\n"; return 0; }
Key Takeaways
- Avoid templated
typedef: Useusingfor alias templates instead—it's supported in C++11 and later, and much cleaner. - Be explicit with signatures: Make sure your alias matches the exact return type and parameter list of the functions you want to store.
- Containers work naturally: Once you have the correct alias, standard containers like
std::vectorhandle templated function pointers just like any other type.
If you're working with an older C++ standard (pre-C11), we can work around it with nested class typedefs, but modern C makes this so much easier—definitely recommend upgrading if you can!
Let me know if you run into any specific compiler errors or have edge cases to cover—I’m happy to help tweak this further.
内容的提问来源于stack exchange,提问作者Riccardo

