{"id":20397522,"url":"https://github.com/jluispcardenas/delegates","last_synced_at":"2025-10-07T19:40:36.986Z","repository":{"id":9198678,"uuid":"11006223","full_name":"jluispcardenas/Delegates","owner":"jluispcardenas","description":"implementation of delegates metodology in C++","archived":false,"fork":false,"pushed_at":"2020-04-25T22:35:33.000Z","size":8,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-15T11:11:20.936Z","etag":null,"topics":["cprogramming","delegates"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jluispcardenas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-06-27T19:49:11.000Z","updated_at":"2021-08-31T20:47:45.000Z","dependencies_parsed_at":"2022-07-21T11:59:04.860Z","dependency_job_id":null,"html_url":"https://github.com/jluispcardenas/Delegates","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/jluispcardenas%2FDelegates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jluispcardenas%2FDelegates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jluispcardenas%2FDelegates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jluispcardenas%2FDelegates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jluispcardenas","download_url":"https://codeload.github.com/jluispcardenas/Delegates/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241945526,"owners_count":20046869,"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":["cprogramming","delegates"],"created_at":"2024-11-15T04:14:40.102Z","updated_at":"2025-10-07T19:40:36.969Z","avatar_url":"https://github.com/jluispcardenas.png","language":"C++","readme":"# C++ Delegates Library\n\ntype-safe implementation of delegates in C++ that provides a flexible callback mechanism similar to C# delegates or JavaScript event handlers.\n\n## Overview\n\nThis library implements a delegate system that allows you to bind and invoke multiple callable objects (functions, lambdas, member functions) with a unified interface. It leverages modern C++ features including variadic templates, perfect forwarding, and `std::function` for optimal performance and type safety.\n\n## Features\n\n- **Type-safe**: Full compile-time type checking with variadic templates\n- **Modern C++**: Uses C++17 features for optimal performance\n- **Flexible binding**: Support for free functions, lambdas, and member functions\n- **Multiple callbacks**: Execute multiple bound functions in sequence\n- **RAII compliant**: Automatic memory management with no manual allocations\n- **Exception safe**: Proper error handling and strong exception safety\n- **Move semantics**: Efficient copying and moving of delegates\n- **Intuitive API**: Clean, easy-to-use interface with operator overloading\n\n## Requirements\n\n- C++17 compatible compiler\n- Standard library with `\u003cfunctional\u003e`, `\u003cvector\u003e`, `\u003calgorithm\u003e`\n\n## Installation\n\nSimply include the `delegate.h` header file in your project:\n\n```cpp\n#include \"delegate.h\"\nusing namespace delegates;\n```\n\n## Usage\n\n### Basic Function Binding\n\n```cpp\n#include \"delegate.h\"\nusing namespace delegates;\n\nint add(int a, int b) {\n    return a + b;\n}\n\n// Create delegate and bind function\ndelegate\u003cint(int, int)\u003e math_delegate;\nmath_delegate.bind(add);\n\n// Invoke the delegate\nint result = math_delegate(5, 3); // Returns 8\n```\n\n### Member Function Binding\n\n```cpp\nclass Calculator {\npublic:\n    int multiply(int a, int b) {\n        return a * b;\n    }\n    \n    void print_result(int value) const {\n        std::cout \u003c\u003c \"Result: \" \u003c\u003c value \u003c\u003c std::endl;\n    }\n};\n\nCalculator calc;\ndelegate\u003cint(int, int)\u003e mult_delegate;\ndelegate\u003cvoid(int)\u003e print_delegate;\n\n// Bind member functions\nmult_delegate.bind(\u0026calc, \u0026Calculator::multiply);\nprint_delegate.bind(\u0026calc, \u0026Calculator::print_result);\n\nint result = mult_delegate(4, 6); // Returns 24\nprint_delegate(result);           // Prints \"Result: 24\"\n```\n\n### Lambda and Multiple Callbacks\n\n```cpp\ndelegate\u003cvoid(const std::string\u0026)\u003e message_delegate;\n\n// Bind multiple callbacks\nmessage_delegate += [](const std::string\u0026 msg) {\n    std::cout \u003c\u003c \"Lambda: \" \u003c\u003c msg \u003c\u003c std::endl;\n};\n\nmessage_delegate += [](const std::string\u0026 msg) {\n    std::cout \u003c\u003c \"Another lambda: \" \u003c\u003c msg \u003c\u003c std::endl;\n};\n\n// All bound callbacks will be executed\nmessage_delegate(\"Hello World!\");\n```\n\n### Advanced Usage\n\n```cpp\n// Check if delegate has callbacks\nif (message_delegate) {\n    message_delegate(\"This will execute\");\n}\n\n// Get number of bound callbacks\nstd::cout \u003c\u003c \"Callbacks count: \" \u003c\u003c message_delegate.size() \u003c\u003c std::endl;\n\n// Clear all callbacks\nmessage_delegate.clear();\n\n// Check if empty\nif (message_delegate.empty()) {\n    std::cout \u003c\u003c \"No callbacks bound\" \u003c\u003c std::endl;\n}\n```\n\n## API Reference\n\n### Core Methods\n\n| Method | Description |\n|--------|-------------|\n| `bind(func)` | Bind a callable object (function, lambda, etc.) |\n| `bind(object, method)` | Bind a member function to an object |\n| `operator()` | Invoke all bound callbacks |\n| `operator+=` | Add a callback (alias for bind) |\n| `operator-=` | Remove a callback (limited functionality) |\n| `clear()` | Remove all callbacks |\n| `size()` | Get number of bound callbacks |\n| `empty()` | Check if no callbacks are bound |\n| `operator bool()` | Check if callbacks are bound |\n\n### Return Value Behavior\n\n- **Void delegates**: All callbacks are executed in order\n- **Non-void delegates**: All callbacks except the last are executed, the return value of the last callback is returned\n\n## Examples\n\n### Event System\n\n```cpp\nclass Button {\nprivate:\n    delegate\u003cvoid()\u003e on_click_;\n    \npublic:\n    delegate\u003cvoid()\u003e\u0026 on_click() { return on_click_; }\n    \n    void click() {\n        if (on_click_) {\n            on_click_();\n        }\n    }\n};\n\n// Usage\nButton button;\nbutton.on_click() += []() { \n    std::cout \u003c\u003c \"Button clicked!\" \u003c\u003c std::endl; \n};\nbutton.on_click() += []() { \n    std::cout \u003c\u003c \"Handling click event\" \u003c\u003c std::endl; \n};\n\nbutton.click(); // Executes both callbacks\n```\n\n### Observer Pattern\n\n```cpp\nclass Subject {\nprivate:\n    delegate\u003cvoid(int)\u003e observers_;\n    int state_ = 0;\n    \npublic:\n    void subscribe(const std::function\u003cvoid(int)\u003e\u0026 observer) {\n        observers_ += observer;\n    }\n    \n    void set_state(int new_state) {\n        state_ = new_state;\n        observers_(state_); // Notify all observers\n    }\n};\n```\n\n## Performance Considerations\n\n- Delegates use `std::function` internally, which may have slight overhead compared to raw function pointers\n- Multiple callbacks are stored in `std::vector` for cache-friendly access\n- Move semantics are used throughout for optimal performance\n- No dynamic memory allocation during callback execution\n\n## Thread Safety\n\nThis implementation is **not thread-safe**. If you need to use delegates across multiple threads, you must provide your own synchronization mechanisms.\n\n## Error Handling\n\n- Binding a null object pointer throws `std::invalid_argument`\n- Invoking an empty non-void delegate throws `std::runtime_error`\n- All operations provide strong exception safety guarantee\n\n## Limitations\n\n- The `operator-=` has limited functionality due to `std::function` comparison constraints\n- Callback removal by value is not fully reliable - consider using the ID-based version for precise removal\n- Not thread-safe out of the box\n\n## Contributing\n\nContributions are welcome! Please ensure:\n\n1. Code follows C++17 standards\n2. All new features include appropriate tests\n3. Documentation is updated for API changes\n4. Code maintains the existing style and conventions\n\n## License\n\nThis project is licensed under the GNU Lesser General Public License v3.0 - see the [LICENSE](LICENSE) file for details.\n\n## Authors\n\n- Jose Luis P. Cardenas (jluis.pcardenas@gmail.com) - Original implementation\n- Contributors welcome\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjluispcardenas%2Fdelegates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjluispcardenas%2Fdelegates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjluispcardenas%2Fdelegates/lists"}