{"id":18736873,"url":"https://github.com/bitwizeshift/delegate","last_synced_at":"2025-10-15T06:45:09.363Z","repository":{"id":52186604,"uuid":"345250648","full_name":"bitwizeshift/Delegate","owner":"bitwizeshift","description":"Delegate is an unbelievably fast, lightweight, and 0-overhead function container.","archived":false,"fork":false,"pushed_at":"2021-05-06T04:56:27.000Z","size":54,"stargazers_count":25,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T14:01:40.085Z","etag":null,"topics":["cpp","cpp17","delegate","fast","function","lightweight","no-dependencies","zero-overhead"],"latest_commit_sha":null,"homepage":"","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/bitwizeshift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["bitwizeshift"],"custom":"https://www.buymeacoffee.com/dsq3XCcBE"}},"created_at":"2021-03-07T03:34:12.000Z","updated_at":"2025-03-11T20:41:50.000Z","dependencies_parsed_at":"2022-08-24T00:41:31.457Z","dependency_job_id":null,"html_url":"https://github.com/bitwizeshift/Delegate","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FDelegate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FDelegate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FDelegate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FDelegate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitwizeshift","download_url":"https://codeload.github.com/bitwizeshift/Delegate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248621206,"owners_count":21134775,"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":["cpp","cpp17","delegate","fast","function","lightweight","no-dependencies","zero-overhead"],"created_at":"2024-11-07T15:22:49.657Z","updated_at":"2025-10-15T06:45:09.260Z","avatar_url":"https://github.com/bitwizeshift.png","language":"C++","readme":"# Unbelievably Fast Delegate\n\n[![Ubuntu Build Status](https://github.com/bitwizeshift/Delegate/workflows/Ubuntu/badge.svg?branch=master)](https://github.com/bitwizeshift/Delegate/actions?query=workflow%3AUbuntu)\n[![macOS Build Status](https://github.com/bitwizeshift/Delegate/workflows/macOS/badge.svg?branch=master)](https://github.com/bitwizeshift/Delegate/actions?query=workflow%3AmacOS)\n[![Windows Build Status](https://github.com/bitwizeshift/Delegate/workflows/Windows/badge.svg?branch=master)](https://github.com/bitwizeshift/Delegate/actions?query=workflow%3AWindows)\n[![Coverage Status](https://coveralls.io/repos/github/bitwizeshift/Delegate/badge.svg?branch=master)](https://coveralls.io/github/bitwizeshift/Delegate?branch=master)\n[![Github Issues](https://img.shields.io/github/issues/bitwizeshift/Delegate.svg)](http://github.com/bitwizeshift/Delegate/issues)\n\u003cbr\u003e\n[![Github Releases](https://img.shields.io/github/v/release/bitwizeshift/Delegate.svg?include_prereleases)](https://github.com/bitwizeshift/Delegate/releases)\n\n**Delegate** is an unbelievably fast, lightweight, and 0-overhead function\ncontainer.\n\n## Teaser\n\n```cpp\ncpp::delegate d = cpp::bind\u003c\u0026std::strlen\u003e();\n\nassert(d(\"hello world\") == 11u);\nassert(d.has_target\u003c\u0026std::strlen\u003e());\n```\n\nSee the [quick start guide](#quick-start) below for how to use this type.\n\n## Features\n\n* [x] Uses absolutely no heap memory\n* [x] Invocations of bound functions execute as fast as raw function pointers\n* [x] Statically binds functions, member functions, and small callable objects\n* [x] `delegate` objects are trivially copyable and trivially destructible\n* [x] Written in modern \u003ckbd\u003eC++17\u003c/kbd\u003e\n* [x] Single-header, **header-only** solution -- easily drops into any project\n\n## Background\n\nThe C++ standard library provides a few type-erased function containers, such as\n`std::function` and `std::packaged_task`, but neither of them provide any\n**guaranteed performance characteristics**. In particular, there is no telling\nhow large an object is, what the cost is to relocating an object, and -- more\nimportantly -- where that object *lives* either on the heap or on the stack.\n\nAlthough type-erasure usually has a cost, the reality of most programs is that\nbound functions are almost always known **at compile time**. The `delegate`\ntype leverages this fact to provide a fast, 0-overhead, lightweight solution.\n\nThe `delegate` object is tiny -- only 2 pointers in size, and trivially cheap\nto copy and destroy. There are only two costs to this design:\n\n1. Functions must be either statically known, or small callable objects such as\n   an empty lambda\n2. To create a `delegate`, you must call a `bind` function.\n\n## Quick-Start\n\n### Binding to delegates\n\nTo create a `cpp::delegate`, you need to pass it the result of a `cpp::bind`\ncall.\n\n`cpp::bind` has overloads for the following bindable targets:\n\n* Statically-specified functions: `cpp::bind\u003c\u0026std::strlen\u003e()`\n* Statically-specified members: `cpp::bind\u003c\u0026std::string::length\u003e(\u0026str)`\n* Local (viewed) functors: `cpp::bind(\u0026func)`\n* Empty trivial functors: `cpp::bind\u003cstd::hash\u003cint\u003e\u003e()`\n* Small functors: `cpp::bind([x}{/* some lambda */})`\n* Opaque function pointers: `cpp::bind( (void(*)) ::dlsym(...) )`\n\nFor example:\n\n```cpp\nstd::string str{\"hello world\"};\n\ncpp::delegate\u003clong()\u003e d = cpp::bind\u003c\u0026std::string::length\u003e(\u0026str);\n\nassert(d() == 11);\n```\n\nBound functions don't need to be exactly the same as the signature, as implicit\nconversions are valid (such as the above example with `long` instead of\n`std::string::size_type`).\n\nAdditionally, you can also leverage CTAD to deduce the function type for any\nfunction pointers or member function pointer inputs:\n\n```cpp\nstd::string str{\"hello world\"};\n\n// deduces cpp::delegate\u003cstd::string::size_type()\u003e\ncpp::delegate d = cpp::bind\u003c\u0026std::string::length\u003e(\u0026str);\n```\n\n### Binding Opaque Functions\n\n`delegate` supports binding both statically specified and opaque specified\nfunction pointers. In general, most uses will be static -- where a user is\nalready aware of what the function pointer is explicitly named, such as:\n\n```cpp\ncpp::delegate d = cpp::bind\u003c\u0026std::strlen\u003e();\n```\n\nHowever there may be cases when interacting with other APIs, such as `::dlsym`,\nwhere the actual symbol for the function is not expressable. In such cases, the\nfunction may be bound opaquely:\n\n```cpp\nauto func = reinterpret_cast\u003cvoid(*)()\u003e(::dlsym(...));\n\ncpp::delegate d = cpp::bind(func);\n```\n\nAlthough this overload also works with statically specified functions as well,\nit should be avoided for general use. Statically specifying functions helps the\ncompiler for the purposes of inlining. Opaque pointers, on the other hand, may\nexperience two separate levels of indirections for the invocation.\n\n### Querying Bound Targets\n\nLike `std::function`, the underlying target of the bound `delegate` may be\nqueried. This may be done using one of the available `cpp::delegate::has_target`\nfunctions. Each overload of `has_target` corresponds to the same inputs as the\nrespective `cpp::bind` call.\n\n```cpp\ncpp::delegate d = cpp::bind\u003c\u0026std::strlen\u003e();\n\nassert( d.has_target\u003c\u0026std::strlen\u003e() );\n```\n\n--------------------------------------------------------------------------------\n\n**Note:** `has_target` will only return `true` if a target was bound using the\nequivalent `cpp::bind` function. This means that a statically-specified function\nbound with `cpp::bind` cannot be queried using the opaque `has_target` overload:\n\n```cpp\ncpp::delegate d = cpp::bind\u003c\u0026std::strlen\u003e();\n\nassert( not d.has_target(\u0026std::strlen) );\n```\n\nAlways make sure not to mix these up if there is a need to query targets!\n\n## Optional Features\n\nAlthough not required, **Delegate** supports custom namespaces\n\n### Using a Custom Namespace\n\nThe `namespace` that `delegate` is defined in is configurable. By default,\nit is defined in `namespace cpp`; however this can be toggled by defining\nthe preprocessor symbol `DELEGATE_NAMESPACE` to be the name of the desired\nnamespace.\n\nThis could be done either through a `#define` preprocessor directive:\n\n```cpp\n#define DELEGATE_NAMESPACE example\n#include \u003cdelegate.hpp\u003e\n\nexample::delegate d = example::bind\u003c\u0026std::strlen\u003e();\n```\n\nOr it could also be defined using the compile-time definition with `-D`, such\nas:\n\n`g++ -std=c++11 -DDELEGATE_NAMESPACE=example test.cpp`\n\n```cpp\n#include \u003cdelegate.hpp\u003e\n\nexample::delegate d = example::bind\u003c\u0026std::strlen\u003e();\n```\n\n## License\n\nThis project is licensed under the extremely permissive\n[Boost License](https://opensource.org/licenses/BSL-1.0):\n\n\u003e Boost Software License - Version 1.0 - August 17th, 2003\n\u003e\n\u003e Copyright (c) 2017, 2018, 2020-2021 Matthew Rodusek\n\u003e\n\u003e Permission is hereby granted, free of charge, to any person or organization\n\u003e obtaining a copy of the software and accompanying documentation covered by\n\u003e this license (the \"Software\") to use, reproduce, display, distribute,\n\u003e execute, and transmit the Software, and to prepare derivative works of the\n\u003e Software, and to permit third-parties to whom the Software is furnished to\n\u003e do so, all subject to the following:\n\u003e\n\u003e The copyright notices in the Software and this entire statement, including\n\u003e the above license grant, this restriction and the following disclaimer,\n\u003e must be included in all copies of the Software, in whole or in part, and\n\u003e all derivative works of the Software, unless such copies or derivative\n\u003e works are solely in the form of machine-executable object code generated by\n\u003e a source language processor.\n\u003e\n\u003e THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\u003e IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\u003e FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n\u003e SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n\u003e FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n\u003e ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n\u003e DEALINGS IN THE SOFTWARE.\n","funding_links":["https://github.com/sponsors/bitwizeshift","https://www.buymeacoffee.com/dsq3XCcBE"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwizeshift%2Fdelegate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitwizeshift%2Fdelegate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwizeshift%2Fdelegate/lists"}