{"id":18736870,"url":"https://github.com/bitwizeshift/lazy","last_synced_at":"2025-04-12T19:32:01.669Z","repository":{"id":81485446,"uuid":"60826849","full_name":"bitwizeshift/Lazy","owner":"bitwizeshift","description":"A lightweight lazy-loading wrapper written in Modern C++","archived":false,"fork":false,"pushed_at":"2017-03-08T04:33:53.000Z","size":250,"stargazers_count":46,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T14:01:43.831Z","etag":null,"topics":["cpp"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","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":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-10T05:51:11.000Z","updated_at":"2025-01-26T18:14:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"3be012cd-0873-4f77-af51-9259237965f1","html_url":"https://github.com/bitwizeshift/Lazy","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FLazy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FLazy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FLazy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitwizeshift%2FLazy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitwizeshift","download_url":"https://codeload.github.com/bitwizeshift/Lazy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248621203,"owners_count":21134774,"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"],"created_at":"2024-11-07T15:22:49.256Z","updated_at":"2025-04-12T19:32:01.662Z","avatar_url":"https://github.com/bitwizeshift.png","language":"C++","readme":"# Lazy\u003cT\u003e\n[![Build Status](https://travis-ci.org/bitwizeshift/Lazy.svg?branch=master)](https://travis-ci.org/bitwizeshift/Lazy)\n[![Build status](https://ci.appveyor.com/api/projects/status/50vmwi1src4ihwmk/branch/master?svg=true)](https://ci.appveyor.com/project/bitwizeshift/lazy/branch/master)\n[![Github Issues](https://img.shields.io/github/issues/bitwizeshift/Lazy.svg)](http://github.com/bitwizeshift/Lazy/issues)\n[![Tested Compilers](https://img.shields.io/badge/compilers-gcc%20%7C%20clang-blue.svg)](#tested-compilers)\n[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://bitwizeshift.github.io/Lazy)\n[![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/bitwizeshift/Lazy/master/LICENSE.md)\n[![Github Releases](https://img.shields.io/github/release/bitwizeshift/Lazy.svg)](https://github.com/bitwizeshift/Lazy/releases)\n\n\n## What is `Lazy\u003cT\u003e`?\n\n`Lazy\u003cT\u003e` is a lightweight lazy-loading wrapper around any arbitrary class `T` written in modern C++. \n\nAll `Lazy` objects have their construction deferred until the latest possible time to ensure the laziest\nconstruction. Upon invocation of a member function, the `Lazy\u003cT\u003e` will instantiate type `T` by\nforwarding `T` the arguments originally supplied with the construction of the `Lazy`.\n \nHere's an example of `Lazy` in action:\n```c++\nauto lazy_string = lazy::make_lazy\u003cstd::string\u003e(\"Hello world!\");\n// Creates Lazy object, doesn't construct std::string\n\n// ... do other operations\n\nstd::cout \u003c\u003c *lazy_string \u003c\u003c \"\\n\"; \n//           ^----------^\n//           Constructs the std::string here for first use here\n\nlazy_string-\u003eresize(10); // Already constructed, using the same std::string\n```\n\n*It's good to be lazy!*\n\nThis library has been written with an emphasis on performance, and aims to reduce unnecessary overhead due to redundant instantiations or duplications. In order to achieve this, deferred argument construction takes copies of all arguments to be passed to the constructor and, at construction time, will use move semantics to invoke the construction of the object. This reduces the need to pay for the cost of duplicate copies, to a cost of copy-and-move instead.\n\n## Why be lazy?\n\nCertain objects may be expensive to construct, especially when they perform complex algorithms, async callbacks, and connections to outside systems. In situations where these objects may not be used within\nall possible execution paths, this can result in wasted cpu cycles. \n\nOften, a lazy-initialization pattern is implemented within the class for the specific-case where it is\nneeded, resulting in a lot of boilerplate code, and possible areas of failure. `Lazy\u003cT\u003e` seeks to make it easier to lazily-initialize entries by handling all of the work with a simple tested API that behaves like a standard c++ smart pointer. \n\n## How to Use\n\n### Inclusion\n\n`Lazy\u003cT\u003e` is a header-only library, making it easy to drop into any new project. \n\nTo start using, add a `-I` to the `include/` directory, and include the header `lazy/Lazy.hpp` from the project.\n\n```c++\n#include \u003clazy/Lazy.hpp\u003e\n\n// use lazy::Lazy\u003cT\u003e \n```\n\n### `Lazy\u003cT\u003e` Objects\n\nAll `Lazy` objects have `operator-\u003e` and `operator*` overloaded, making them behave similar to a smart pointer or an iterator. The underlying type will remain uninstantiated until such time that certain functions are accessed -- such as when the operators `-\u003e` or `*` are accessed. At which point it will attempt a construction of the underlying type `T`.\n\nThis means that the type managed by a `Lazy` does _not_ require a default or trivial constructor in order for this to properly operate; it simply requires a function to inform it how to instantiate the type at a later point.\n\n### Construction\n\nThere are various ways to construct lazy objects through `Lazy\u003cT\u003e` depending on the required needs. \n\n1. Default construction\n2. `make_lazy\u003cT\u003e` utility for forwarding arguments\n3. Function delegation for manually specifying construction/destruction behavior\n4. Copy/Move construction/assignment\n\n#### 1. Default Construction\n\nIf you have a type that is to be lazily constructed with the default or trivial constructor, use the default constructor for the `Lazy` class. This isn't particularly exciting, but this is the default behavior.\n\n```c++\nauto lazy_foo = lazy::Lazy\u003cFoo\u003e();\n\n// ...\n\nlazy_foo-\u003edo_something(); // constructs Foo object with Foo()\n```\n\n#### 2. `make_lazy\u003cT\u003e` Utility Function\n\nIf no custom logic is required to construct the type `T` other than the constructor arguments, then you can easily make use of the `lazy::make_lazy\u003cT\u003e(...)` utility function. \n\n`make_lazy` behaves similarly to `std::make_shared` and `std::make_unique` in that it forwards its arguments to the underlying type. The difference is that these arguments are stored until which time that the `Lazy` object is constructed for its first use.\n\nNote that this means that arguments supplied to `make_lazy` will require a copy constructor, since copies are used. This is necessary to avoid dangling reference problems when the values passed go out of scope prior to construction of the object.\n\nAn example of using `make_lazy`:\n```c++\n\nauto lazy_string = lazy::make_lazy\u003cstd::string\u003e(\"Hello World\",5);\n\n// do something\n\nstd::cout \u003c\u003c *lazy_string \u003c\u003c std::endl; \n//           ^~~~~~~~~~~^\n//           Constructs std::string with the constructor std::string(const char*, size_t)\n```\n\n#### 3. Function delegation\n\nIf more complex logic is required for the construction of the `T` object, you can supply a construction (and optionally destruction) function-like object (function pointer, member-function,functor, or lambda).\n\nThe _construction_ function simple must return a `std::tuple` containing the types that will be forwarded to the constructor (I recommend making use of `std::make_tuple` to simplify this). \n\nThe _destruction_ function must take type `T\u0026` as a parameter and return `void`. The purpose of the destruction function is to give the chance to clean up anything that may not be managed by a destructor (or, in the case of using fundamental types like pointers, the chance to delete). The _destruction_ function will be called prior to calling `T`'s destructor.\n\nAn example of where this may become useful:\n```c++\nauto open_file = [](){\n  return std::make_tuple(fopen(\"some/file/path\",\"r\"));\n};\nauto close_file = [](FILE* ptr){\n  fclose(ptr);\n};\nauto lazy_file = lazy::Lazy\u003cFILE*\u003e(open_file,close_file);\n\n// somewhere else\nuse_file(*lazy_file); // constructs the lazy file object\n```\n#### 4. Copy/Move Constructor/Assignment\n\nA `Lazy` object is able to be constructed out of an instance of the underlying type `T` through copy or move construction. The same can also be done with instances of `Lazy\u003cT\u003e` as well.\n\nIn the case of `T` objects, the types will be used for deferred construction later on through a call to the copy or move constructors.\nIn the case of `Lazy\u003cT\u003e` objects, they are constructed immediately, provided the `Lazy` being copied or moved has also itself been instantiated. If it is not, only the construction/destruction functions are copied or moved.\n\nSimilarly, the `Lazy` objects can be assigned to other `Lazy` objects, or directly to the type `T`. \nFor assignments to type `T`, if the lazy is not already constructed, it will lazily construct itself prior to assignment to avoid the need for a copy or move constructor. \nFor assignments to type `Lazy`, if the lazy being assigned is already initialized, the value will be \nassigned to the currently constructed `Lazy`. If it is uninitialized, only the constructor to the \ntype will be assigned to defer instantiation until later use.\n\nExamples:\n```c++\nauto a = lazy::make_lazy\u003cstd::string\u003e(\"Hello world\");\nauto b = a; // copy construction\n```\n\n##\u003ca name=\"tested-compilers\"\u003e\u003c/a\u003e Tested Compilers\n\nThe following compilers are currently being tested through continuous integration with [Travis](https://travis-ci.org/bitwizeshift/Lazy).\n\nNote that `Lazy` only works on compiler that provide proper conformance for c++11, meaning this\ndoes not properly work on g++ before 4.8 \n\n| Compiler              | Operating System                   |\n|-----------------------|------------------------------------|\n| g++ 4.9.3             | Ubuntu 14.04.3 TLS                 |\n| g++ 5.3.0             | Ubuntu 14.04.3 TLS                 |\n| g++ 6.1.1             | Ubuntu 14.04.3 TLS                 |\n| clang 3.5.0           | Ubuntu 14.04.3 TLS                 |\n| clang 3.6.2           | Ubuntu 14.04.3 TLS                 |\n| clang 3.8.0           | Ubuntu 14.04.3 TLS                 |\n| clang xcode 6.0       | Darwin Kernel 13.4.0 (OSX 10.9.5)  |\n| clang xcode 6.1       | Darwin Kernel 14.3.0 (OSX 10.10.3) |\n| clang xcode 7.0       | Darwin Kernel 14.5.0 (OSX 10.10.5) |\n| clang xcode 7.3       | Darwin Kernel 15.5.0 (OSX 10.11.5) |\n| clang xcode 8.0       | Darwin Kernel 15.6.0 (OSX 10.11.6) |\n| Visual Studio 14 2015\t| Windows Server 2012 R2 (x64)       |\n\n##\u003ca name=\"license\"\u003e\u003c/a\u003e License\n\n\u003cimg align=\"right\" src=\"http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png\"\u003e\n\nThe class is licensed under the [MIT License](http://opensource.org/licenses/MIT):\n\nCopyright \u0026copy; 2016 [Matthew Rodusek](http://rodusek.me/)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwizeshift%2Flazy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitwizeshift%2Flazy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitwizeshift%2Flazy/lists"}