Fn
A thin wrapper that turns a (member) function pointer into a type
Install / Use
/learn @uyha/FnREADME
Function pointers as lambda
This library provides a trait for querying information about a function pointer type, whether it is a free function pointer, a member function pointer, noexcept, etc. It also provides a thin wrapper that turns (member) function pointers into individual types. It is intended to make (member) function pointers behave like lambda but with a more convenient syntax. C's variadic function pointers are not supported.
Quickstart
#include <cassert>
#include <river/fn.hpp>
void function() {}
struct A {
void function(){};
int a{0};
};
struct Callable {
void operator()() const {}
};
int main() {
static_assert(river::fn_trait_of<function>::type == river::FnType::free_fn_ptr);
constexpr auto func = river::fn<function>{};
func();
A a{};
static_assert(river::fn_trait_of<&A::function>::type == river::FnType::member_fn_ptr);
constexpr auto mem_func = river::fn<&A::function>{};
mem_func(a);
static_assert(river::fn_trait_of<&A::a>::type == river::FnType::member_var_ptr);
constexpr auto mem_var = river::fn<&A::a>{};
mem_var(a);
static_assert(river::fn_trait<Callable>::type == river::FnType::invocable);
constexpr auto callable = river::Fn{Callable{}};
callable();
A const b{};
auto overloading_func = river::over_fn<&A::function>{};
overloading_func(a);
overloading_func(A{});
auto member = river::over_fn<&A::a>{};
assert(member(a) == 0);
assert(member(b) == 0);
assert(member(A{}) == 0);
}
Usage
This is a header only library, just copy fn.hpp to your project and start using it. This library requires C++17.
Features
fn_trait
This library provides the fn_trait class that provides details about:
- invocables (classes with an
operator(), passing classes with an overload set ofoperator()will create a compile time error) - free function pointers
- member function pointers
- member variable pointers
The following table shows the details provided by the fn_trait:
| Input | FnType | is_noexcept | return_t | object_t | arguments |
| ------------------------ | ---------------- | ------------- | ---------- | ---------- | -------------------- |
| Invocables | invocable | bool | R | T | type_list<Args...> |
| Free function pointers | free_fn_ptr | bool | R | - | type_list<Args...> |
| Member function pointers | member_fn_ptr | bool | R | T | type_list<Args...> |
| Member variable pointers | member_var_ptr | - | R | T | type_list<> |
fn_trait<T>::arguments is a river::type_list, in other to use this list, you
can have a function template that accepts river::type_list as normal parameter and
have the template parameters being a pack. The following snippet demonstrate this:
template<typename... Args>
auto use_args(river::type_list<Args...>) {
// do something with `Args`
}
// `Args` will be `int`, `bool`
use_args(river::fn_trait<void(*)(int, bool)>::arguments{});
// lambda
void unpack_with_lambda() {
auto lambda = []<typename... Args>(river::type_list<Args...>) {
//do something with `Args`
};
// `Args` will be `int`, `bool`
lambda(river::fn_trait<void (*)(int, bool)>::arguments{});
}
This library was originally developed to provide a feature for constructing guards and
actions for sml easily from free functions and member functions. The fn class
template is designed for that (although it fails to compile on MSVC when propagating
noexcept). fn provides just one operator() function that accepts a reasonable set
of arguments and not an overload set of it since sml fails to call the correct
function when there is an overload set. If you need an object that can be called with
all the possible valid arguments, then overloading_fn should be used instead.
If you want to create the function objects with runtime arguments, you can use Fn and
OverFn. They have the equivalent functionality with fn, and over_fn, but they
accept the function pointers/invocables as runtime parameters instead of compile time
parameters.
Performance
This library incurs no overhead when fn and overloading_fn are used in constexpr
context and/or maximum optimization.
Same TU function pointer
https://godbolt.org/z/E14P31dvK
#include <river/fn.hpp>
int test(){
return 42;
}
int main(){
const auto f = river::fn<test>;
return f();
}
test():
mov eax, 42
ret
main:
mov eax, 42
ret
Different TU function pointer
https://godbolt.org/z/s6rnr835M
#include <river/fn.hpp>
int test();
int main(){
const auto f = river::fn<test>;
return f();
}
main:
jmp test()
Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.8kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
