{"id":13630019,"url":"https://github.com/Naios/function2","last_synced_at":"2025-04-17T13:31:14.405Z","repository":{"id":2942075,"uuid":"41765706","full_name":"Naios/function2","owner":"Naios","description":"Improved and configurable drop-in replacement to std::function that supports move only types, multiple overloads and more","archived":false,"fork":false,"pushed_at":"2024-08-17T16:07:18.000Z","size":549,"stargazers_count":545,"open_issues_count":12,"forks_count":46,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-08T21:38:20.739Z","etag":null,"topics":["function","function-wrapper","functional","type-erasure"],"latest_commit_sha":null,"homepage":"http://naios.github.io/function2","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Naios.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-01T22:02:42.000Z","updated_at":"2024-11-04T22:29:43.000Z","dependencies_parsed_at":"2022-08-06T13:00:36.189Z","dependency_job_id":"8a5f2c91-891f-4dd4-83e8-178558169bb4","html_url":"https://github.com/Naios/function2","commit_stats":{"total_commits":340,"total_committers":12,"mean_commits":"28.333333333333332","dds":"0.061764705882352944","last_synced_commit":"2d3a878ef19dd5d2fb188898513610fac0a48621"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Ffunction2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Ffunction2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Ffunction2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Naios%2Ffunction2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Naios","download_url":"https://codeload.github.com/Naios/function2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249344770,"owners_count":21254733,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["function","function-wrapper","functional","type-erasure"],"created_at":"2024-08-01T22:01:27.408Z","updated_at":"2025-04-17T13:31:14.158Z","avatar_url":"https://github.com/Naios.png","language":"C++","readme":"\n# fu2::function an improved drop-in replacement to std::function\n\n![](https://img.shields.io/badge/Version-4.0.0-0091EA.svg) ![](https://img.shields.io/badge/License-Boost-blue.svg) [![Build Status](https://travis-ci.org/Naios/function2.svg?branch=master)](https://travis-ci.org/Naios/function2) [![Build status](https://ci.appveyor.com/api/projects/status/1tl0vqpg8ndccats/branch/master?svg=true)](https://ci.appveyor.com/project/Naios/function2/branch/master)\n\nProvides improved implementations of `std::function`:\n\n- **copyable** `fu2::function`\n- **move-only** `fu2::unique_function` (capable of holding move only types)\n- **non-owning** `fu2::function_view` (capable of referencing callables in a non owning way)\n\nthat provide many benefits and improvements over `std::function`:\n\n- [x] **const**, **volatile**, **reference** and **noexcept** correct (qualifiers are part of the `operator()` signature)\n- [x] **convertible** to and from `std::function` as well as other callable types\n- [x] **adaptable** through `fu2::function_base` (internal capacity, copyable and exception guarantees)\n- [x] **overloadable** with an arbitrary count of signatures (`fu2::function\u003cbool(int), bool(float)\u003e`)\n- [x] **full allocator support** in contrast to `std::function`, which doesn't provide support anymore\n- [x] **covered** by many unit tests and continuous integration services (*GCC*, *Clang* and *MSVC*)\n- [x] **header only**, just copy and include `function.hpp` in your project\n- [x] **permissively licensed** under the **boost** license\n\n\n## Table of Contents\n\n* **[Documentation](#documentation)**\n  * **[How to use](#how-to-use)**\n  * **[Constructing a function](#constructing-a-function)**\n  * **[Non copyable unique functions](#non-copyable-unique-functions)**\n  * **[Convertibility of functions](#convertibility-of-functions)**\n  * **[Adapt function2](#adapt-function2)**\n* **[Performance and optimization](#performance-and-optimization)**\n  * **[Small functor optimization](#small-functor-optimization)**\n  * **[Compiler optimization](#compiler-optimization)**\n  * **[std::function vs fu2::function](#stdfunction-vs-fu2function)**\n* **[Coverage and runtime checks](#coverage-and-runtime-checks)**\n* **[Compatibility](#compatibility)**\n* **[License](#licence)**\n* **[Similar implementations](#similar-implementations)**\n\n## Documentation\n\n### How to use\n\n**function2** is implemented in one header (`function.hpp`), no compilation is required.\nJust copy the `function.hpp` header in your project and include it to start.\nIt's recommended to import the library as git submodule using CMake:\n\n```sh\n# Shell:\ngit submodule add https://github.com/Naios/function2.git\n```\n\n```cmake\n# CMake file:\nadd_subdirectory(function2)\n# function2 provides an interface target which makes it's\n# headers available to all projects using function2\ntarget_link_libraries(my_project function2)\n```\n\nUse `fu2::function` as a wrapper for copyable function wrappers and `fu2::unique_function` for move only types.\nThe standard implementation `std::function` and `fu2::function` are convertible to each other, see [the chapter convertibility of functions](#convertibility-of-functions) for details.\n\nA function wrapper is declared as following:\n```c++\nfu2::function\u003cvoid(int, float) const\u003e\n// Return type ~^   ^     ^     ^\n// Parameters  ~~~~~|~~~~~|     ^\n// Qualifier ~~~~~~~~~~~~~~~~~~~|\n```\n\n* **Return type**: The return type of the function to wrap.\n* **Arguments**: The argument types of the function to wrap.\n  Any argument types are allowed.\n* **Qualifiers**: There are several qualifiers allowed:\n  - **no qualifier** provides `ReturnType operator() (Args...)`\n    - Can be assigned from const and no const objects (*mutable lambdas* for example).\n  - **const** provides `ReturnType operator() (Args...) const`\n    - Requires that the assigned functor is const callable (won't work with *mutable lambdas*),\n  - **volatile** provides `ReturnType operator() (Args...) volatile`\n    - Can only be assigned from volatile qualified functors.\n  - **const volatile** provides `ReturnType operator() (Args...) const volatile`\n    - Same as const and volatile together.\n  - **r-value (one-shot) functions** `ReturnType operator() (Args...) \u0026\u0026`\n    - one-shot functions which are invalidated after the first call (can be mixed with `const`, `volatile` and `noexcept`). Can only wrap callable objects which call operator is also qualified as `\u0026\u0026` (r-value callable). Normal (*C*) functions are considered to be r-value callable by default.\n  - **noexcept functions** `ReturnType operator() (Args...) noexcept`\n    - such functions are guaranteed not to throw an exception (can be mixed with `const`, `volatile` and `\u0026\u0026`). Can only wrap functions or callable objects which call operator is also qualified as `noexcept`. Requires enabled C++17  compilation to work (support is detected automatically). Empty function calls to such a wrapped function will lead to a call to `std::abort` regardless the wrapper is configured to support exceptions or not (see [adapt function2](#adapt-function2)).\n* **Multiple overloads**: The library is capable of providing multiple overloads:\n  ```cpp\n  fu2::function\u003cint(std::vector\u003cint\u003e const\u0026),\n                int(std::set\u003cint\u003e const\u0026) const\u003e fn = [] (auto const\u0026 container) {\n                  return container.size());\n                };\n  ```\n\n### Constructing a function\n\n`fu2::function` and `fu2::unique_function` (non copyable) are easy to use:\n\n```c++\nfu2::function\u003cvoid() const\u003e fun = [] {\n  // ...\n};\n\n// fun provides void operator()() const now\nfun();\n```\n\n### Non copyable unique functions\n\n`fu2::unique_function` also works with non copyable functors/ lambdas.\n\n```c++\nfu2::unique_function\u003cbool() const\u003e fun = [ptr = std::make_unique\u003cbool\u003e(true)] {\n  return *ptr;\n};\n\n// unique functions are move only\nfu2::unique_function\u003cbool() const\u003e otherfun = std::move(fun):\n\notherfun();\n```\n\n\n### Non owning functions\n\nA `fu2::function_view` can be used to create a non owning view on a persistent object. Note that the view is only valid as long as the object lives.\n\n```c++\nauto callable = [ptr = std::make_unique\u003cbool\u003e(true)] {\n  return *ptr;\n};\n\nfu2::function_view\u003cbool() const\u003e view(callable);\n```\n\n### Convertibility of functions\n\n`fu2::function`, `fu2::unique_function` and `std::function` are convertible to each other when:\n\n- The return type and parameter type match.\n- The functions are both volatile or not.\n- The functions are const correct:\n  - `noconst = const`\n  - `const = const`\n  - `noconst = noconst`\n- The functions are copyable correct when:\n  - `unique = unique`\n  - `unique = copyable`\n  - `copyable = copyable`\n- The functions are reference correct when:\n  - `lvalue = lvalue`\n  - `lvalue = rvalue`\n  - `rvalue = rvalue`\n- The functions are `noexcept` correct when:\n  - `callable = callable`\n  - `callable = noexcept callable `\n  - `noexcept callable = noexcept callable`\n\n| Convertibility from \\ to | fu2::function | fu2::unique_function | std::function |\n| ------------------------ | ------------- | -------------------- | ------------- |\n| fu2::function            | Yes           | Yes                  | Yes           |\n| fu2::unique_function     | No            | Yes                  | No            |\n| std::function            | Yes           | Yes                  | Yes           |\n\n```c++\nfu2::function\u003cvoid()\u003e fun = []{};\n// OK\nstd::function\u003cvoid()\u003e std_fun = fun;\n// OK\nfu2::unique_function\u003cvoid()\u003e un_fun = fun;\n\n// Error (non copyable -\u003e copyable)\nfun = un_fun;\n// Error (non copyable -\u003e copyable)\nfun = un_fun;\n\n```\n\n### Adapt function2\n\nfunction2 is adaptable through `fu2::function_base` which allows you to set:\n\n- **IsOwning**: defines whether the function owns its contained object\n- **Copyable:** defines if the function is copyable or not.\n- **Capacity:** defines the internal capacity used for [sfo optimization](#small-functor-optimization):\n```cpp\nstruct my_capacity {\n  static constexpr std::size_t capacity = sizeof(my_type);\n  static constexpr std::size_t alignment = alignof(my_type);\n};\n```\n- **IsThrowing** defines if empty function calls throw an `fu2::bad_function_call` exception, otherwise `std::abort` is called.\n- **HasStrongExceptGuarantee** defines whether the strong exception guarantees shall be met.\n- **Signatures:** defines the signatures of the function.\n\nThe following code defines an owning  function with a variadic signature which is copyable and sfo optimization is disabled:\n\n```c++\ntemplate\u003ctypename Signature\u003e\nusing my_function = fu2::function_base\u003ctrue, true, fu2::capacity_none, true, false, Signature\u003e;\n```\n\nThe following code defines a non copyable function which just takes 1 argument, and has a huge capacity for internal sfo optimization. Also it must be called as r-value.\n\n```c++\ntemplate\u003ctypename Arg\u003e\nusing my_consumer = fu2::function_base\u003ctrue, false, fu2::capacity_fixed\u003c100U\u003e,\n                                       true, false, void(Arg)\u0026\u0026\u003e;\n\n// Example\nmy_consumer\u003cint, float\u003e consumer = [](int, float) { }\nstd::move(consumer)(44, 1.7363f);\n```\n\n## Performance and optimization\n\n### Small functor optimization\n\nfunction2 uses small functor optimization like the most common `std::function` implementations which means it allocates a small internal capacity to evade heap allocation for small functors.\n\nSmart heap allocation moves the inplace allocated functor automatically to the heap to speed up moving between objects.\n\nIt's possible to disable small functor optimization through setting the internal capacity to 0.\n\n\n## Coverage and runtime checks\n\nFunction2 is checked with unit tests and valgrind (for memory leaks), where the unit tests provide coverage for all possible template parameter assignments.\n\n## Compatibility\n\nTested with:\n\n- Visual Studio 2017+ Update 3\n- Clang 3.8+\n- GCC 5.4+\n\nEvery compiler with modern C++14 support should work.\n*function2* only depends on the standard library.\n\n## License\n*function2* is licensed under the very permissive Boost 1.0 License.\n\n## Similar implementations\n\nThere are similar implementations of a function wrapper:\n\n- [pmed/fixed_size_function](https://github.com/pmed/fixed_size_function)\n- stdex::function - A multi-signature function implementation.\n- multifunction - Example from [Boost.TypeErasure](http://www.boost.org/doc/html/boost_typeerasure/examples.html#boost_typeerasure.examples.multifunction), another multi-signature function.\n- std::function - [Standard](http://en.cppreference.com/w/cpp/utility/functional/function).\n- boost::function - The one from [Boost](http://www.boost.org/doc/libs/1_55_0/doc/html/function.html).\n- func::function - From this [blog](http://probablydance.com/2013/01/13/a-faster-implementation-of-stdfunction/).\n- generic::delegate - [Fast delegate in C++11](http://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11), also see [here](https://code.google.com/p/cpppractice/source/browse/trunk/).\n- ssvu::FastFunc - Another Don Clugston's FastDelegate, as shown [here](https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/QgvHF7YMi3o).\n- [cxx_function::function](https://github.com/potswa/cxx_function) - By David Krauss\n\nAlso check out the amazing [**CxxFunctionBenchmark**](https://github.com/jamboree/CxxFunctionBenchmark) which compares several implementations.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNaios%2Ffunction2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNaios%2Ffunction2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNaios%2Ffunction2/lists"}