{"id":19075324,"url":"https://github.com/gershnik/intrusive_shared_ptr","last_synced_at":"2026-03-13T23:33:25.770Z","repository":{"id":143477839,"uuid":"213690683","full_name":"gershnik/intrusive_shared_ptr","owner":"gershnik","description":"Intrusive reference counting smart pointer, highly configurable reference counted base class and various adapters","archived":false,"fork":false,"pushed_at":"2025-04-15T06:08:19.000Z","size":343,"stargazers_count":17,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-18T19:41:58.145Z","etag":null,"topics":["c-plus-plus-17","c-plus-plus-20","cplusplus","cplusplus-17","cplusplus-20","cpp","cpp17","cpp20","header-only","no-dependencies","reference-count","reference-counting","weak-reference"],"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/gershnik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null}},"created_at":"2019-10-08T16:06:38.000Z","updated_at":"2025-04-15T06:07:30.000Z","dependencies_parsed_at":null,"dependency_job_id":"5de11e53-1a93-46ba-a69a-c22b6a6bb9ac","html_url":"https://github.com/gershnik/intrusive_shared_ptr","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gershnik%2Fintrusive_shared_ptr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gershnik%2Fintrusive_shared_ptr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gershnik%2Fintrusive_shared_ptr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gershnik%2Fintrusive_shared_ptr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gershnik","download_url":"https://codeload.github.com/gershnik/intrusive_shared_ptr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251599196,"owners_count":21615481,"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":["c-plus-plus-17","c-plus-plus-20","cplusplus","cplusplus-17","cplusplus-20","cpp","cpp17","cpp20","header-only","no-dependencies","reference-count","reference-counting","weak-reference"],"created_at":"2024-11-09T01:54:22.293Z","updated_at":"2026-03-13T23:33:25.761Z","avatar_url":"https://github.com/gershnik.png","language":"C++","readme":"# Intro \nThis is yet another implementation of an intrusive [reference counting](http://en.wikipedia.org/wiki/Reference_counting) \n[smart pointer](http://en.wikipedia.org/wiki/Smart_pointer), highly configurable reference counted base class and adapters.\n\nThe code requires C++17 or above compiler.\n\nIt is known to work with:\u003cbr/\u003e\nXcode 11 or above\u003cbr/\u003e\nMicrosoft Visual Studio 2019 or above\u003cbr/\u003e\nClang 8 or above\u003cbr/\u003e\nGCC 7.4.0 or above\u003cbr/\u003e\n\nIt can be used either as a classical header-only library or as C++ module (experimental).\n\nDocumentation and formal tests are work in progress.\n\n\u003c!-- TOC depthfrom:2 --\u003e\n\n- [Why bother?](#why-bother)\n    - [Named conversions from raw pointers](#named-conversions-from-raw-pointers)\n    - [No ADL](#no-adl)\n    - [Support for output parameters](#support-for-output-parameters)\n    - [Support for operator-\u003e*](#support-for-operator-)\n    - [Atomic access](#atomic-access)\n    - [Trivial ABI](#trivial-abi)\n    - [Correct implementation of a \"reference counted base\" class](#correct-implementation-of-a-reference-counted-base-class)\n    - [Support for weak pointers](#support-for-weak-pointers)\n- [Integration](#integration)\n    - [CMake via FetchContent](#cmake-via-fetchcontent)\n    - [Conan](#conan)\n    - [Vcpkg](#vcpkg)\n    - [Platform package managers](#platform-package-managers)\n    - [Building and installing on your system](#building-and-installing-on-your-system)\n        - [Basic use](#basic-use)\n        - [CMake package](#cmake-package)\n        - [Via pkg-config](#via-pkg-config)\n    - [Copying to your sources](#copying-to-your-sources)\n- [Usage](#usage)\n    - [Basics](#basics)\n    - [Using provided base classes](#using-provided-base-classes)\n    - [Supporting weak pointers](#supporting-weak-pointers)\n    - [Using with Apple CoreFoundation types](#using-with-apple-corefoundation-types)\n    - [Using with Microsoft COM interfaces](#using-with-microsoft-com-interfaces)\n    - [Using with Python objects](#using-with-python-objects)\n    - [Using with non-reference counted types](#using-with-non-reference-counted-types)\n    - [Atomic operations](#atomic-operations)\n- [Constexpr functionality](#constexpr-functionality)\n- [Module support](#module-support)\n- [Reference](#reference)\n\n\u003c!-- /TOC --\u003e\n\n## Why bother?\nThere are multiple other intrusive smart pointers available including one from [Boost](https://www.boost.org/doc/libs/1_71_0/libs/smart_ptr/doc/html/smart_ptr.html#intrusive_ptr)\nand there was even a [proposal](http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0468r0.html) \nto add one to the standard C++ library, so why create another one?\nUnfortunately, as far as I can tell, all existing implementations, and that includes the standard library proposal at the time\nof this writing, suffer from numerous deficiencies that make them hard or annoying to use in real life code. \nThe most serious problems addressed here are as follows\n\n### Named conversions from raw pointers\nAll other libraries offer a conversion in the form \n`smart_ptr(T * p);`\nIn my opinion, this is an extremely bad idea. When looking at a call like `smart_ptr(foo())` can you quickly tell whether this adds a reference count or \"attaches\" the smart pointer to a raw one? That's right, you cannot! The answer depends \non the smart pointer implementation or even on specific traits used. This makes the behavior invisible and hard to predict at the **call site**. It guarantees that someone, somewhere will make a wrong assumption. In my experience, almost all reference counting bugs happen on the **boundary** between code that uses smart and raw pointers where such conversions are abundant. \nJust like any form of dangerous cast this one has to be **explicit** in calling code. As an aside, ObjectiveC ARC did it right\nwith their explicit and visible `__bridge` casts between raw and smart pointers.\nNote that having a boolean argument (like what Boost and many other implementations do) in constructor isn't a solution.\nCan you quickly tell what `smart_ptr(p, true)` does? Is it \"true, add reference\" or \"true, copy it\"?\n\nThis library uses named functions to perform conversion. You see exactly what is being done at the call site.\n\n### No ADL \n\nMany libraries use [ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup) to find \"add reference\" and \n\"release reference\" functions for the underlying type.\nThat is, they have expressions like `add_ref(p)` in their implementation, and expect a function named `add_ref` that accepts pointer to the underlying type is supposed to be found via ADL.\nThis solution is great in many cases but it breaks when working with some C types like Apple's `CTypeRef`. This one is actually a typedef to `void *` so if you have an `add_ref` that accepts it, you have just made every unrelated `void *` reference counted (with very bad results if you accidentally put a wrong object into a smart pointer).\nA better way to define how reference counting is done is to pass a traits class to the smart pointer. (The standard library proposal gets this one right).\n\nThis library uses traits.\n\n### Support for output parameters\n\nOften times you need to pass smart pointer as an output parameter to a C function that takes `T **`\nMany other smart pointers either \n- ignore this scenario, requiring you to introduce extra raw pointer and unsafe code, or\n- overload `operator\u0026` which is a horrendously bad idea (it breaks lots of generic code which assumes that `\u0026foo` gives\n  an address of foo, not something else)\nThe right solution is to have a proxy class convertible to `T **`.\n\nSince C++23 the standard library provides `std::out_ptr` and `std::inout_ptr` to deal with this issue. This library\nfully supports those when they are available.\n\nWhen standard library support is not available, this library also exposes `get_output_param()` and `get_inout_param` \nmethods that return an inner proxy class (which behaves similarly to `std::out_ptr_t`/`std::inout_ptr`) \n\n### Support for `operator-\u003e*`\n\nThis might seem to be a minor thing but is really annoying in generic code. For some reason no smart pointers bother to provide\n`operator-\u003e*` so that pointers to members could be accessed via the same syntax as for raw pointers. In non-generic code\nyou can always work around it via `(*p).*whatever` but in generic code this is not an option.\n\n### Atomic access\n\nSometimes you need to operate on smart pointers atomically. To the best of my knowledge no library currently provides this functionality.\n\nThis library provides a specialization of `std::atomic\u003cintrusive_shared_ptr\u003c...\u003e\u003e` extending to it the normal `std::atomic` semantics.\n\n### Trivial ABI\n\nWhen built with CLang compiler `intrusive_shared_ptr` is marked with [\\[\\[clang::trivial_abi\\]\\]](https://clang.llvm.org/docs/AttributeReference.html#trivial-abi) \nattribute. A good description of what this attribute does and why it is important\nfor performance can be found [here](https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/).\nAnother take on the performance issue as a comment on standard library proposal can be found \n[here](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1351r0.html#params).\n[This page](doc/trivial_abi.md) contains details on why this is a good idea and why concerns about order of destruction do not really matter here.\n\n### Correct implementation of a \"reference counted base\" class\n\nThis is not directly a problem with smart pointers but with the base classes often provided together with them to implement an\nintrusively counted class. Very often they contain subtle bugs (see \n['A note on implementing reference counted objects'](doc/reference_counting.md) for more details). It is also tricky to \ncreate a base class that can work well for different requirements without compromising efficiency.\n\n### Support for weak pointers\n\nContinuing on the base class theme, when doing intrusive reference counting, supporting (or not) weak pointers is the responsibility \nof the counted class. Supporting weak pointers also usually involves tradeoffs in terms of performance or memory consumption. \nThis library base class allows user to enable a decent implementation of weak pointers via policy based design. \n\n\n## Integration\n\n### CMake via FetchContent\n\n```cmake\ninclude(FetchContent)\n...\n\nFetchContent_Declare(isptr\n    GIT_REPOSITORY  https://github.com/gershnik/intrusive_shared_ptr.git\n    GIT_TAG         v1.9  #use the tag, branch or sha you need\n    GIT_SHALLOW     TRUE\n)\n...\nFetchContent_MakeAvailable(isptr)\n...\n\n#To use header files:\ntarget_link_libraries(mytarget\nPRIVATE\n  isptr::isptr\n)\n\n#To use C++ module (the second param is the visibilty)\nisptr_add_module(mytarget PRIVATE)\n```\n\u003e ℹ\u0026#xFE0F; _[What is FetchContent?](https://cmake.org/cmake/help/latest/module/FetchContent.html)_\n\n### Conan\n\nAdd `intrusive_shared_ptr/1.9` to your conanfile.\n\n### Vcpkg\n\nIn classic mode, run the following vcpkg command:\n```bash\nvcpkg install intrusive-shared-ptr\n```\n\nIn manifest mode, run the following vcpkg command in your project directory:\n```bash\nvcpkg add port intrusive-shared-ptr\n```\n\n### Platform package managers\n\nOn Debian based systems `intrusive-shared-ptr` might be available via APT.\n\nYou can consult https://pkgs.org/search/?q=libisptr-dev for up-to-date availability information.\n\nIf available, it can be installed via\n\n```bash\napt install libisptr-dev\n```\n\n### Building and installing on your system\n\nYou can also build and install this library on your system using CMake.\n\n1. Download or clone this repository into SOME_PATH\n2. On command line:\n```bash\ncd SOME_PATH\ncmake -S . -B build \n\n#Optional\n#cmake --build build --target run-test\n\n#install to /usr/local\nsudo cmake --install build\n#or for a different prefix\n#cmake --install build --prefix /usr\n```\n\nOnce the library has been installed it can be used in the following ways:\n\n#### Basic use \n\nTo use the header files set the include directory to `\u003cprefix\u003e/include` where `\u003cprefix\u003e` \nis the install prefix from above.\n\nTo use C++ module (if enabled during the build) include `\u003cprefix\u003e/include/intrusive_shared_ptr/isptr.cppm` \nin your build.\n\n\n#### CMake package\n\n```cmake\nfind_package(isptr)\n\n#To use header files:\ntarget_link_libraries(mytarget\nPRIVATE\n  isptr::isptr\n)\n\n#To use C++ module (the second param is the visibilty)\nisptr_add_module(mytarget PRIVATE)\n```\n\n#### Via `pkg-config`\n\nAdd the output of `pkg-config --cflags isptr` to your compiler flags.\n\nNote that the default installation prefix `/usr/local` might not be in the list of places your\n`pkg-config` looks into. If so you might need to do:\n```bash\nexport PKG_CONFIG_PATH=/usr/local/share/pkgconfig\n```\nbefore running `pkg-config`\n\n\n### Copying to your sources\n\nYou can also simply download this repository from [Releases](https://github.com/gershnik/intrusive_shared_ptr/releases) page \n(named `intrusive_shared_ptr-X.Y.tar.gz`) and unpack it somewhere in your source tree.\n\nTo use header files add the `inc` sub-directory to your include path.\n\nTo use the module add `modules/isptr.cppm` to your build. \n\n## Usage\n\n### Basics\n\nAll the types in this library are declared in `namespace isptr`. For brevity the namespace is omitted below.\nAdd `isptr::` prefix to all the type or use `using` declaration in your own code.\n\nThe header `\u003cintrusive_shared_ptr/intrusive_shared_ptr.h\u003e`/module `isptr` provides a template\n\n```cpp\ntemplate\u003cclass T, class Traits\u003e\nclass intrusive_shared_ptr\u003cT, Traits\u003e;\n```\n\nWhere `T` is the type of the pointee and `Traits` a class that should provide 2 static functions that look like this\n\n```cpp\nstatic void add_ref(SomeType * ptr) noexcept\n{  \n    //increment reference count. ptr is guaranteed to be non-nullptr\n}\nstatic void sub_ref(SomeType * ptr) noexcept\n{ \n    //decrement reference count. ptr is guaranteed to be non-nullptr\n}\n```\n\n`SomeType *` should be a pointer type to which `T *` is convertible to. It is possible to make `add_ref` and `sub_ref`\ntemplates, if desired, though this is usually not necessary.\n\n\nTo create `intrusive_shared_ptr` from a raw `T *` there are 2 functions:\n\n```cpp\n//pass the smart pointer in without changing the reference count\ntemplate\u003cclass T, class Traits\u003e\nintrusive_shared_ptr\u003cT, Traits\u003e intrusive_shared_ptr\u003cT, Traits\u003e::noref(T * p) noexcept;\n\n//adopt the pointer and bump the reference count\ntemplate\u003cclass T, class Traits\u003e\nintrusive_shared_ptr\u003cT, Traits\u003e intrusive_shared_ptr\u003cT, Traits\u003e::ref(T * p) noexcept\n```\n\nIt is possible to use `intrusive_shared_ptr` directly but the name is long and ugly so a better approach is to\nwrap in a typedef and wrapper functions like this\n\n```cpp\nstruct my_type\n{};\n\nstruct my_intrusive_traits\n{\n    static void add_ref(my_type * ptr) noexcept; //implement\n    static void sub_ref(my_type * ptr) noexcept; //implement\n};\n\ntemplate\u003cclass T\u003e\nusing my_ptr = intrusive_shared_ptr\u003cT, my_intrusive_traits\u003e;\n\ntemplate\u003cclass T\u003e \nmy_ptr\u003cT\u003e my_retain_func(T * ptr) {\n    return my_ptr\u003cT\u003e::ref(ptr);\n}\ntemplate\u003cclass T\u003e \nmy_ptr\u003cT\u003e my_attach_func(T * ptr) {\n    return my_ptr\u003cT\u003e::noref(ptr);\n}\n\n```\n\nThe library provides such wrappers for some common scenarios. If you fully control the definition of `my_type` then\nit is possible to simplify things even further with header `refcnt_ptr.h`. It adapts `intrusive_shared_ptr` to traits\nexposed as inner type `refcnt_ptr_traits`. You can use it like this:\n\n```cpp\n#include \u003cintrusive_shared_ptr/refcnt_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\nstruct my_type\n{\n  struct refcnt_ptr_traits\n  {\n      static void add_ref(my_type * ptr) noexcept; //implement\n      static void sub_ref(my_type * ptr) noexcept; //implement\n  };\n};\n\n//now you can use refcnt_ptr\u003cmy_type\u003e for the pointer type and refcnt_attach and refcnt_retain free functions e.g.\n\n//create from raw pointer (created with count 1)\nfoo raw = new my_type();\nrefcnt_ptr\u003cmy_type\u003e p1 = refcnt_attach(raw);\n\n//create directly\nauto p1 = make_refcnt\u003cmy_type\u003e();\n\n//assign from raw pointer bumping reference count\nrefcnt_ptr\u003cmy_type\u003e p2;\np2 = refcnt_retain(raw);\n\n\n```\n\n\n### Using provided base classes\n\nTo implement `my_type` above the library provides a base class you can inherit from which will do the right thing.\n\n```cpp\n#include \u003cintrusive_shared_ptr/ref_counted.h\u003e\n#include \u003cintrusive_shared_ptr/refcnt_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\nclass foo : ref_counted\u003cfoo\u003e\n{\n    friend ref_counted;\npublic:    \n    void method();\nprivate:\n    ~foo() noexcept = default; //prevent manual deletion\n};\n\n//you can use auto to declare p1, p2 and p3. The full type is spelled out for\n//demonstration purposes only\n\n//attach from raw pointer (created with count 1)\nrefcnt_ptr\u003cfoo\u003e p1 = refcnt_attach(new foo()); \n\n//create directly\nrefcnt_ptr\u003cfoo\u003e p2 = make_refcnt\u003cfoo\u003e();\n\n//assign from raw pointer bumping reference count\nfoo * raw = ...\nrefcnt_ptr\u003cfoo\u003e p3 = refcnt_retain(raw);\n\n```\n\nThe type of the reference count is `int` by default. If you need to you can customize it. \n\n```cpp\n\nclass tiny : ref_counted\u003ctiny, ref_counted_flags::none, char\u003e //use char as count type\n{\n  friend ref_counted;\n\n  char c;\n};\n\nstatic_assert(sizeof(tiny) == 2);\n\n```\n\nMore details can be found in [this document](doc/ref_counted.md)\n\n### Supporting weak pointers\n\nIf you want to support weak pointers you need to tell `ref_counted` about it. Since weak pointers include overhead\neven if you never create one, by default they are disabled.\n\n```cpp\n#include \u003cintrusive_shared_ptr/ref_counted.h\u003e\n#include \u003cintrusive_shared_ptr/refcnt_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\nclass foo : weak_ref_counted\u003cfoo\u003e //alias for ref_counted\u003cfoo, ref_counted_flags::provide_weak_references\u003e\n{\n    void method();\n};\n\nrefcnt_ptr\u003cfoo\u003e p1 = refcnt_attach(new foo());\nfoo::weak_ptr w1 = p1-\u003eget_weak_ptr();\nrefcnt_ptr\u003cfoo\u003e p2 = w1-\u003elock();\n```\n\nNote that you cannot customize the type of reference count if you support weak pointers - it will always be `intptr_t`.\nMore details can be found in [this document](doc/ref_counted.md)\n\n### Using with Apple CoreFoundation types\n\n```cpp\n\n#include \u003cintrusive_shared_ptr/apple_cf_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\n//Use auto in real code. Type is spelled out for clarity\ncf_ptr\u003cCStringRef\u003e str = cf_attach(CFStringCreateWithCString(nullptr, \n                                                             \"Hello\", \n                                                             kCFStringEncodingUTF8));\nstd::cout \u003c\u003c CFStringGetLength(str.get());\n\nCFArrayRef raw = ...;\n//Use auto in real code.\ncf_ptr\u003cCFArrayRef\u003e array = cf_retain(raw);\n\n```\n\n### Using with Microsoft COM interfaces\n\n```cpp\n\n#include \u003cintrusive_shared_ptr/com_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\ncom_shared_ptr\u003cIStream\u003e pStream;\n//Before C++23\nCreateStreamOnHGlobal(nullptr, true, pStream.get_output_param());\n//With C++23 and later\nCreateStreamOnHGlobal(nullptr, true, std::out_ptr(pStream));\npStream-\u003eWrite(....);\n\n```\n\n### Using with Python objects\n\n```cpp\n#include \u003cintrusive_shared_ptr/python_ptr.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing namespace isptr;\n\nauto str = py_attach(PyUnicode_FromString(\"Hello\"));\nstd::cout \u003c\u003c PyUnicode_GetLength(str.get());\n\n```\n\n### Using with non-reference counted types\n\nOn occasion when you have a code that uses intrusive reference counting a lot you might need to handle a type\nwhich you cannot modify and which is not by itself reference counted. \nIn such situation you can use an adapter (if you prefer derivation) or wrapper (if you prefer containment) that makes it such\n\nAdapter:\n```cpp\n#include \u003cintrusive_shared_ptr/ref_counted.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing counted_map = ref_counted_adapter\u003cstd::map\u003cstring, int\u003e\u003e;\n\nauto ptr = make_refcnt\u003ccounted_map\u003e();\n(*ptr)[\"abc\"] = 7;\nstd::cout \u003c\u003c ptr-\u003esize();\n\nusing weakly_counted_map = weak_ref_counted_adapter\u003cstd::map\u003cstring, int\u003e\u003e;\n\nauto ptr1 = make_refcnt\u003cweakly_counted_map\u003e();\n(*ptr1)[\"abc\"] = 7;\nstd::cout \u003c\u003c ptr1-\u003esize();\nfoo::weak_ptr w1 = p1-\u003eget_weak_ptr();\nrefcnt_ptr\u003cweakly_counted_map\u003e p2 = w1-\u003elock();\n```\n\nWrapper:\n```cpp\n#include \u003cintrusive_shared_ptr/ref_counted.h\u003e\n//Or, if using modules:\n//import isptr;\n\nusing counted_map = ref_counted_wrapper\u003cstd::map\u003cstring, int\u003e\u003e;\n\nauto ptr = make_refcnt\u003ccounted_map\u003e();\nptr-\u003ewrapped()[\"abc\"] = 7;\nstd::cout \u003c\u003c ptr-\u003ewrapped().size();\n\nusing weakly_counted_map = weak_ref_counted_wrapper\u003cstd::map\u003cstring, int\u003e\u003e;\n\nauto ptr1 = make_refcnt\u003cweakly_counted_map\u003e();\nptr1-\u003ewrapped()[\"abc\"] = 7;\nstd::cout \u003c\u003c ptr1-\u003ewrapped().size();\nfoo::weak_ptr w1 = p1-\u003eget_weak_ptr();\nrefcnt_ptr\u003cweakly_counted_map\u003e p2 = w1-\u003elock();\n```\n\n### Atomic operations\n\nThe library provides a partial specialization \n\n```cpp\n\ntemplate \u003cclass T, class Traits\u003e\nstd::atomic\u003cintrusive_shared_ptr\u003cT, Traits\u003e\u003e;\n\n```\n\nwhich exposes normal `std::atomic` functionality. For example:\n\n```cpp\n\nusing my_ptr = intrusive_shared_ptr\u003cmy_type, my_intrusive_traits\u003e;\n\nusing my_atomic_ptr = std::atomic\u003cmy_ptr\u003e;\n\nmy_ptr ptr = ...;\nmy_atomic_ptr aptr = ptr;\n\nptr = aptr.load();\n//or\nptr = aptr;\n\naptr.store(ptr);\n//or\naptr = ptr;\n\nmy_ptr ptr1 = aptr.exchange(ptr);\n\n//etc.\n\n```\n\n## Constexpr functionality\n\nWhen built with C++20 compiler `intrusive_shared_ptr` is fully constexpr capable. You can do things like\n\n```cpp\n\nusing my_ptr = intrusive_shared_ptr\u003cmy_type, my_intrusive_traits\u003e;\n\nconstexpr my_ptr foo;\n\n```\n\nDue to non-default destructors this functionality is not available on C++17\n\n## Module support\n\nSince version 1.5 this library support being used as a C++ module. \nThis mode is currently **experimental**. Please report bugs if you encounter any issues.\n\nIn order to use C++ modules you need a compiler that supports them. \nCurrently CLang \u003e= 16 and MSVC toolset \u003e= 14.34 are definitely known to work. \nOther compilers/versions may or may not work.\n\nIf using CMake follow the requirements at [cmake-cxxmodules](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html). \n\nThe library consists of a single module file at [modules/isptr.cppm](modules/isptr.cppm). \nThis file is auto-generated from all the library headers. Include it in your build.\n\n## Reference\n\n* [intrusive_shared_ptr.h](doc/intrusive_shared_ptr.md)\n* [refcnt_ptr.h](doc/refcnt_ptr.md)\n* [ref_counted.h](doc/ref_counted.md)\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgershnik%2Fintrusive_shared_ptr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgershnik%2Fintrusive_shared_ptr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgershnik%2Fintrusive_shared_ptr/lists"}