#include <function_pointer.h>
void CallMe(int input) { /* ... */ }
class Example {
void CallMe(int input) { /* ... */ }
}
void PassMeAFunction(FunctionPointer<void(int)> fn) {
// Invoke function pointer
fn.invoke(123);
// Store any kind of FunctionPointer<*> in a container (with type erasure)
std::vector<IFunctionPointerBase*> _functionPointers;
_functionPointers.push_back(fn);
}
void Example() {
// Store a static function pointer to call later
auto functionPointer = function_pointer(CallMe);
// Store a member function pointer to call later
Example example;
auto memberFunctionPointer = function_pointer(&example, &Example::CallMe);
// Or a lambda (with or without captures)
auto lambdaFunctionPointer = function_pointer([]() { /* ... */ });
// Call the function pointers
functionPointer.invoke(123);
memberFunctionPointer.invoke(123);
lambdaFunctionPointer.invoke(123);
// Implicit convestions to FunctionPointer:
PassMeAFunction(CallMe);
PassMeAFunction(&example, &Example::CallMe);
PassMeAFunction([]() { /* ... */ });
}
Easily store and call function pointers and member function pointers in C++
add_repositories("MrowrLib https://github.com/MrowrLib/Packages.git")
add_requires("function_pointer")
target("Example")
add_packages("function_pointer")
add_executable(Example main.cpp)
# Find function_pointer and link it to your target
find_package(function_pointer CONFIG REQUIRED)
target_link_libraries(Example PRIVATE function_pointer::function_pointer)
{
"dependencies": ["mrowr-function-pointer"]
}
{
"default-registry": {
"kind": "git",
"repository": "https://github.com/microsoft/vcpkg.git",
"baseline": "95252eadd63118201b0d0df0b4360fa613f0de84"
},
"registries": [
{
"kind": "git",
"repository": "https://github.com/MrowrLib/Packages.git",
"baseline": "cd78ba157aae728a1e08f4e84dc1c9c64314510d",
"packages": ["mrowr-function-pointer"]
}
]
}
Update the default-registry baseline to the latest commit from https://github.com/microsoft/vcpkg
Update the MrowrLib/Packages baseline to the latest commit from https://github.com/MrowrLib/Packages
I needed to store both:
- function pointers
- member function pointers (from different types)
And I needed a pointer I could pass around to refer to the function pointer and invoke it.
So I made this.
Note: I need this for scenarios when I'm working with true function pointers.
If you have the option of usingstd::function
instead, highly recommend using that!
#include <function_pointer.h>
void CallMe(int input) { /* ... */ }
class Example {
void CallMe(int input) { /* ... */ }
};
void Example() {
// Store a static function pointer to call later
auto functionPointer = function_pointer(CallMe);
// Store a member function pointer to call later
Example example;
auto memberFunctionPointer = function_pointer(&example, &Example::CallMe);
// Or a lambda (with or without captures)
auto lambdaFunctionPointer = function_pointer([]() { /* ... */ });
// Call the function pointers
functionPointer.invoke(123);
memberFunctionPointer.invoke(123);
lambdaFunctionPointer.invoke(123);
}
If you want to specify required return type and arguments for a function pointer, you can use the FunctionPointer
template.
// Using the `function_pointer` helper function
// which returns std::unique_ptr<FunctionPointer<ReturnType(Args...)>>
auto functionPointer = function_pointer(CallMe); // Static function pointer
auto functionPointer = function_pointer<this, &Example::CallMe); // Member function pointer
auto functionPointer = function_pointer([]() { /* ... */ }); // Lambda or std::function
// There is also a helper which returns a raw pointer
auto* functionPointer = new_function_pointer(CallMe); // Static function pointer
auto* functionPointer = new_function_pointer<this, &Example::CallMe); // Member function pointer
auto* functionPointer = new_function_pointer([]() { /* ... */ }); // Lambda or std::function
If you declare a function which accepts a FunctionPointer
as an argument, you must specify the return type and arguments.
void MyFunction(FunctionPointer<void(int)> functionPointer) {
functionPointer.invoke(123);
}
If you want a pure abstract virtual interface, you can use the IFunctionPointer
interface.
void MyFunction(IFunctionPointer<void(int)>* functionPointer) {
functionPointer->invoke(123);
}
If you want to store a function pointer without specifying the return type or arguments, you can use the IFunctionPointerBase
interface.
This template uses type erasure, allowing you to easily store instances without knowing the return type or arguments.
// Using the `function_pointer` helper function
// which returns std::unique_ptr<IFunctionPointerBase>
auto functionPointer = function_pointer_base(CallMe); // Static function pointer
auto functionPointer = function_pointer_base<this, &Example::CallMe); // Member function pointer
auto functionPointer = function_pointer_base([]() { /* ... */ }); // Lambda or std::function
// There is also a helper which returns a raw pointer
IFunctionPointerBase* functionPointer = new_function_pointer_base(CallMe); // Static function pointer
IFunctionPointerBase* functionPointer = new_function_pointer_base<this, &Example::CallMe); // Member function pointer
IFunctionPointerBase* functionPointer = new_function_pointer_base([]() { /* ... */ }); // Lambda or std::function
IFunctionPointerBase*
is the reason why this library exists.
You can store a IFunctionPointerBase*
and invoke it later, without knowing the return type or arguments.
You can easily store various IFunctionPointerBase*
of different types in the same container.
Use however, no attribution required.
BSD Zero Clause License (SPDX: 0BSD)
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.