SkillAgentSearch skills...

Fn

A thin wrapper that turns a (member) function pointer into a type

Install / Use

/learn @uyha/Fn
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Function pointers as lambda

C/C++ CI

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 of operator() 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

View on GitHub
GitHub Stars8
CategoryDevelopment
Updated1y ago
Forks0

Languages

C++

Security Score

70/100

Audited on Sep 10, 2024

No findings