{"id":13418965,"url":"https://github.com/rsms/immutable-cpp","last_synced_at":"2025-05-09T01:44:16.082Z","repository":{"id":66105778,"uuid":"63969694","full_name":"rsms/immutable-cpp","owner":"rsms","description":"Persistent immutable data structures for C++","archived":false,"fork":false,"pushed_at":"2016-07-23T02:53:56.000Z","size":125,"stargazers_count":284,"open_issues_count":0,"forks_count":15,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-05-07T21:13:54.420Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/rsms.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-22T17:00:13.000Z","updated_at":"2025-03-10T12:37:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"59ab7d6d-9d6d-4f34-91a6-1b02e0a313d7","html_url":"https://github.com/rsms/immutable-cpp","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/rsms%2Fimmutable-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fimmutable-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fimmutable-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rsms%2Fimmutable-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rsms","download_url":"https://codeload.github.com/rsms/immutable-cpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253176444,"owners_count":21866141,"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":[],"created_at":"2024-07-30T22:01:09.481Z","updated_at":"2025-05-09T01:44:16.064Z","avatar_url":"https://github.com/rsms.png","language":"C++","readme":"# Immutable++\n\nPersistent immutable data structures providing practically O(1) for appends, updates and lookups based on work by Rich Hickey and by consequence Phil Bagwell.\n\n```cc\nauto a = Array\u003cint\u003e::empty();\na = a-\u003epush(1);\na = a-\u003epush(2);\na = a-\u003epush(3);\n\nauto b = a-\u003epush(4);\nb = b-\u003eset(2, 33);\n\nfor (auto\u0026 value : *a) {\n  printf(\"%d \", value);\n}\n// output: 1 2 3\n\nfor (auto\u0026 value : *b) {\n  printf(\"%d \", value);\n}\n// output: 1 2 33 4\n```\n\nConfigure:\n```sh\n./configure.py --debug\n```\n\nTo build and run tests:\n```sh\nninja \u0026\u0026 build/debug/bin/test\n```\n\nTo build and debug:\n```sh\nninja \u0026\u0026 lldb -bo r build/debug/bin/test\n```\n\n## Array\u003cT\u003e\n\nA persistent random-accessible ordered collection of value type `T`.\n\nSynopsis:\n\n```cc\nstruct Array\u003cT\u003e {\n  static ref\u003cArray\u003e empty();\n  static ref\u003cArray\u003e create(std::initializer_list\u003ctypename Y\u003e\u0026\u0026);\n  static ref\u003cArray\u003e create(typename Iterable\u0026\u0026);\n  static ref\u003cArray\u003e create(const typename Iterable\u0026);\n  static ref\u003cArray\u003e create(Iterator\u0026\u0026 begin, const Iterator\u0026 end);\n  static ref\u003cArray\u003e create(Iterator\u0026 begin, const Iterator\u0026 end);\n  static ref\u003cArray\u003e create(typename It\u0026 begin, const typename It\u0026 end);\n  static ref\u003cArray\u003e create(typename It\u0026\u0026 begin, const typename It\u0026 end);\n\n  uint32 size() const;\n  \n  ref\u003cArray\u003e push(Value\u003cT\u003e*) const;\n  ref\u003cArray\u003e push(typename Any\u0026\u0026) const;\n  ref\u003cArray\u003e push(Iterator\u0026\u0026 begin, const Iterator\u0026 end) const;\n  ref\u003cArray\u003e push(Iterator\u0026 begin, const Iterator\u0026 end) const;\n  ref\u003cArray\u003e push(typename It\u0026\u0026 begin, const typename It\u0026 end) const;\n  ref\u003cArray\u003e push(typename It\u0026 begin, const typename It\u0026 end) const;\n\n  ref\u003cArray\u003e          set(uint32 i, typename Any\u0026\u0026) const;\n  ref\u003cArray\u003e          set(uint32 i, Value\u003cT\u003e*) const;\n  const T\u0026            get(uint32 i) const;\n  Iterator            find(uint32 i) const;\n  const ref\u003cValue\u003cT\u003e\u003e findValue(uint32 i) const;\n  const ref\u003cValue\u003cT\u003e\u003e getValue(uint32 i) const;\n  const T\u0026            first() const;\n  const T\u0026            last() const;\n  const ref\u003cValue\u003cT\u003e\u003e firstValue() const;\n  const ref\u003cValue\u003cT\u003e\u003e lastValue() const;\n  \n  ref\u003cArray\u003e pop() const;\n  ref\u003cArray\u003e rest() const;\n  ref\u003cArray\u003e concat(ref\u003cArray\u003e) const;\n  ref\u003cArray\u003e slice(uint32 start, uint32 end=END) const;\n  ref\u003cArray\u003e splice(uint32 start, uint32 end, typename It\u0026\u0026 it, const typename It\u0026 endit) const;\n  ref\u003cArray\u003e splice(uint32 start, uint32 end, Iterator\u0026\u0026 it) const;\n  ref\u003cArray\u003e splice(uint32 start, uint32 end, Iterator\u0026 it) const;\n  ref\u003cArray\u003e splice(uint32 start, uint32 end, ref\u003cArray\u003e) const;\n  ref\u003cArray\u003e without(uint32 start, uint32 end=END) const;\n  \n  ref\u003cTransientArrayT\u003e asTransient() const;\n  ref\u003cArray\u003e           modify(typename Func\u0026\u0026 fn) const;\n  \n  int compare(const ref\u003cArray\u003e\u0026 other) const;\n\n  Iterator        begin(uint32 start=0, uint32 end=END) const;\n  const Iterator\u0026 end() const;\n}\n```\n\n#### empty() → Array\nThe empty array\n\n```cc\nref\u003cArray\u003e Array::empty();\n```\n\nExample:\n\n```cc\nauto a = Array\u003cint\u003e::empty();\nauto b = Array\u003cstd::string\u003e::empty();\nassert(a-\u003esize() == 0 \u0026\u0026 b-\u003esize() == 0);\nassert(a.ptr() == b.ptr()); // actually same underlying memory\n```\n\n#### create(...) → Array\nCreate an array from values.\n\n```cc\nstatic ref\u003cArray\u003e create(std::initializer_list\u003ctypename Y\u003e\u0026\u0026);         // 1\nstatic ref\u003cArray\u003e create(typename Iterable\u0026\u0026);                         // 2\nstatic ref\u003cArray\u003e create(const typename Iterable\u0026);                    // 3\nstatic ref\u003cArray\u003e create(Iterator\u0026\u0026 begin, const Iterator\u0026 end);       // 4\nstatic ref\u003cArray\u003e create(Iterator\u0026 begin, const Iterator\u0026 end);        // 5\nstatic ref\u003cArray\u003e create(typename It\u0026 begin, const typename It\u0026 end);  // 6\nstatic ref\u003cArray\u003e create(typename It\u0026\u0026 begin, const typename It\u0026 end); // 7\n```\n\n- Form 1 takes an initializer list of any value type, and then constructs T's using the provided values in the initializer list by moving the values to T's constructor.\n- Form 2 and 3 reads values from something that provides begin() and end() which returns [std::input_iterator](http://en.cppreference.com/w/cpp/concept/InputIterator) and constructs T's with those values.\n- Form 4 and 5 are specializations of 6 \u0026 7 for [Array\u003cT\u003e::Iterator](#arrayiterator) that avoids copying of values (instead it just references the same values.)\n- Form 6 and 7 reads values from something that conforms to [std::input_iterator](http://en.cppreference.com/w/cpp/concept/InputIterator) and constructs T's with those values.\n\n\nExamples:\n\n```cc\n// Emplacing three T's with values from implicit initializer list\nauto a = Array\u003cint\u003e::create({1, 2, 3});\n\n// Constructing T's (std::string) with values of a different type (const char*)\nauto b = Array\u003cstd::string\u003e::create(\n  std::initializer_list\u003cconst char*\u003e{\"Foo\", \"Bar\"});\n\n// Constructing T's by moving values from an iterable\nauto c = Array\u003cint\u003e::create(std::vector({1, 2, 3}));\n\n// Constructoring T's by copying iterator values\nstd::vector values({1, 2, 3});\nauto d = Array\u003cint\u003e::create(values.begin(), values.end());\n```\n\n#### size() → uint32\n\nNumber of values in the array\n\n\n#### get(index), first(), last() → T\n\nDirectly access value at index without checking that index is within bounds. If index is out-of bounds, the behavior is undefined.\n\n```cc\nconst T\u0026 get(uint32 index) const;\nconst T\u0026 first() const;\nconst T\u0026 last() const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na-\u003eget(1); // == 2\na-\u003elast(); // == 3\na-\u003eget(9); // probably crash from memory violation. probably.\n```\n\n#### findValue(index), getValue(index), firstValue(), lastValue() → Value\n\nAccess [Value](#value) at index. Form 1 returns nullptr if index is out-of bounds. All other forms have undefined behavior if index is out-of bounds or if the array is empty.\n\n```cc\nconst ref\u003cValue\u003cT\u003e\u003e findValue(uint32 i) const; // 1\nconst ref\u003cValue\u003cT\u003e\u003e getValue(uint32 i) const;  // 2\nconst ref\u003cValue\u003cT\u003e\u003e firstValue() const;        // 3\nconst ref\u003cValue\u003cT\u003e\u003e lastValue() const;         // 4\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na-\u003efindValue(1)-\u003evalue; // == 2\na-\u003efindValue(9);        // == nullptr\na-\u003elastValue()-\u003evalue;  // == 3\n```\n\n#### find(index) → Iterator\nReturns an [Array\u003cT\u003e::Iterator](#arrayiterator) to value at index. If index is out-of bounds, the end() iterator is returned.\n\n```cc\nIterator find(uint32 i) const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\nauto I = a-\u003efind(1);\n*I; // == 2\na-\u003efind(9) == a-\u003eend();\n```\n\n#### push(value) → Array\nProduces an array with value(s) added to the end. This operation is sometimes called \"conj\" or \"conjoin\" in functional programming.\n\n```cc\nref\u003cArray\u003e push(Any\u0026\u0026) const;                                               // 1\nref\u003cArray\u003e push(Value\u003cT\u003e*) const;                                           // 2\nref\u003cArray\u003e push(InputIt\u0026\u0026 begin, const InputIt\u0026 end) const;                 // 3\nref\u003cArray\u003e push(InputIt\u0026 begin, const InputIt\u0026 end) const;                  // 4\nref\u003cArray\u003e push(Array::Iterator\u0026\u0026 begin, const Array::Iterator\u0026 end) const; // 5\nref\u003cArray\u003e push(Array::Iterator\u0026 begin, const Array::Iterator\u0026 end) const;  // 6\n```\n\n- Form 1 constructs a value of type T in-place with Any (anything.)\n- Form 2 references a value without any construction or copying of T.\n- Form 3 and 4 takes arguments that conforms to [std::input_iterator](http://en.cppreference.com/w/cpp/concept/InputIterator). The value type of InputIt must be either [Value\u003cT\u003e](#value) or some value that T can be constructed from, like T itself or an argument accepted by T's constructor.\n- Form 5 and 6 are specializations of 3 \u0026 4 for [Array\u003cT\u003e::Iterator](#arrayiterator) that avoids copying values.\n\nExamples:\n\n```cc\n// Simple example\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na = a-\u003epush(4); // a =\u003e [1, 2, 3, 4]\n\n// Example of constructing multiple Ts from arguments\n// passed via initializer_list:\nstruct Monster {\n  Monster(int hp, int xp=1) : hp(hp), xp(xp) {}\n  int hp;\n  int xp;\n};\nauto monsters = Array\u003cMonster\u003e::empty();\nauto args = std::initializer_list\u003cint\u003e{10, 15, 20};\nmonsters = monsters-\u003epush(args.begin(), args.end());\nfor (auto\u0026 monster : *monsters) {\n  printf(\"hp: %d, xp: %d\\n\", monster.hp, monster.xp);\n}\n// output:\n// hp: 10, xp: 1\n// hp: 15, xp: 1\n// hp: 20, xp: 1\n```\n\n#### cons(value) → Array\nReturns an array with value added to the beginning. This operation is sometimes called \"push_front\" or \"shift\" in some mutative implementations. Note that you can use `splice` to form arrays with multiple new items added to the beginning.\n\nForm 1 constructs a value of type T in-place with Any (anything), while form 2 references a value without any construction or copying of T.\n\n```cc\nref\u003cArray\u003e cons(typename Any\u0026\u0026) const; // 1\nref\u003cArray\u003e cons(Value\u003cT\u003e*) const;      // 2\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na = a-\u003econs(0); // =\u003e [0, 1, 2, 3]\n```\n\n#### set(index, value) → Array\nSet value at index, where index must be less than size(). Returns nullptr if i is out-of bounds. For form 1, value can be anything that can be used to construct a T.\n\n```cc\nref\u003cArray\u003e set(uint32 index, typename Any\u0026\u0026) const; // 1\nref\u003cArray\u003e set(uint32 i, Value\u003cT\u003e*) const;          // 2\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na = a-\u003eset(1, 22); // =\u003e [1, 22, 3]\n```\n\n#### pop() → Array\nReturns an array without the last value.\n\n```cc\nref\u003cArray\u003e pop() const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na = a-\u003epop(); // =\u003e [1, 2]\n```\n\n#### rest() → Array\nReturns an array without the first value. This operation is sometimes called \"pop_front\" or \"unshift\" in some mutative implementations.\n\n```cc\nref\u003cArray\u003e rest() const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\na = a-\u003erest(); // =\u003e [2, 3]\n```\n\n#### concat(Array) → Array\nReturns an array that combines the target array's values followed by the argument array's values.\n\n```cc\nref\u003cArray\u003e concat(ref\u003cArray\u003e) const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\nauto b = Array\u003cint\u003e::create({4, 5, 6});\na = a-\u003econcat(b); // =\u003e [1, 2, 3, 4, 5, 6]\n```\n\n#### slice(start[, end]) → Array\nReturns a slice of the target array, from start up until (but not including) end. If end is not provided, the effect is the same as setting end to Array::size(). nullptr is returned if start and/or end is out-of bounds.\n\n```cc\nref\u003cArray\u003e slice(uint32 start, uint32 end=END) const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\na = a-\u003eslice(1, 4); // =\u003e [2, 3, 4]\n```\n\n#### splice(start, end, source...) → Array\nReplaces values within the range [start, end) with values from an iterator or another array. Form 1 accepts anything that implements [std::input_iterator](http://en.cppreference.com/w/cpp/concept/InputIterator). Form 2 and 3 accepts [Array\u003cT\u003e::Iterator](#arrayiterator). Form 4 uses another array for the source of values to be spliced in.\n\n```cc\nref\u003cArray\u003e splice(uint32 start, uint32 end,\n                  typename It\u0026\u0026 it, const typename It\u0026 endit) const; // 1\nref\u003cArray\u003e splice(uint32 start, uint32 end, Iterator\u0026\u0026 it) const;    // 2\nref\u003cArray\u003e splice(uint32 start, uint32 end, Iterator\u0026 it) const;     // 3\nref\u003cArray\u003e splice(uint32 start, uint32 end, ref\u003cArray\u003e) const;       // 4\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\nauto b = Array\u003cint\u003e::create({66, 77, 88});\na = a-\u003esplice(1, 4, b); // =\u003e [1, 66, 77, 88, 5]\n```\n\n#### without(start[, end]) → Array\nRemoves values within the range [start, end). Returns null if i is out-of bounds. Note that `without(X,Y)` equivalent to `splice(X,Y,end(),end())`.\n\n```cc\nref\u003cArray\u003e without(uint32 start, uint32 end=END) const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\na = a-\u003ewithout(1, 4); // =\u003e [1, 5]\n```\n\n#### asTransient() → TransientArray\nReturns a [TransientArray](#transientarray) contaning the same values as this array. Transient arrays are useful for efficient batch modifications to an array.\n\n```cc\nref\u003cTransientArrayT\u003e asTransient() const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\nauto t = a-\u003easTransient();\nt-\u003eset(0, 11)\n -\u003eset(2, 33); // can be chained\nt-\u003eset(4, 55); // or not, since operations mutate t.\na = t-\u003emakePersistent(); // =\u003e [11, 2, 33, 4, 55]\n```\n\n#### modify(func(TransientArray)) → Array\nApply batch modifications using a transient. This method is really just a convenience for asTransient() ... makePersistent() as seen in the example above.\n\n```cc\nref\u003cArray\u003e modify(typename Func\u0026\u0026 fn) const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\na = a-\u003emodify([] (auto t) { // auto arg is a C++14 feature\n  t-\u003eset(0, 11)\n   -\u003eset(2, 33); // can be chained\n  t-\u003eset(4, 55); // or not, since operations mutate t.\n});\n// a =\u003e [11, 2, 33, 4, 55]\n```\n\n#### compare(Array) → int\nCompare the values of the target array with the values in the array passed as an argument. Uses std::less\u003cT\u003e to compare values and thus T must support std::less (e.g. by implementing `operator\u003c`)\n\n```cc\nint compare(const ref\u003cArray\u003e\u0026 other) const;\n\n// Example:\nauto a = Array\u003cstd::string\u003e::create({\"Foo\", \"Bar\", \"Cat\"});\nauto b = Array\u003cstd::string\u003e::create({\"Foo\", \"Bar\", \"Cat\"});\nauto c = Array\u003cstd::string\u003e::create({\"Foo\", \"Bar\", \"Catz\"});\na-\u003ecompare(b); // == 0\na-\u003ecompare(c); // == 1\nc-\u003ecompare(a); // == -1\n```\n\n#### begin([start[, endIndex]]), end() → Iterator\nbegin() returns a new iterator that accesses the range [start,endIndex). If endIndex is not given, it has the same effect as passing `size()`. If start is not given, it has the same effect as passing `0`. end() returns the end iterator.\n\n```cc\nIterator begin(uint32 start=0, uint32 end=END) const;\nconst Iterator\u0026 end() const;\n\n// Example:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\nfor (auto I = a-\u003ebegin(); I != a-\u003eend(); ++I) {\n  printf(\"%d \", *I);\n} // output: 1 2 3\n\n// Example of iterating over a range:\nauto a = Array\u003cint\u003e::create({1, 2, 3, 4, 5});\nfor (auto I = a-\u003ebegin(1, 4); I != a-\u003eend(); ++I) {\n  printf(\"%d \", *I);\n} // output: 2 3 4\n\n// Example of using non-standard method valid() (not using end())\nauto a = Array\u003cint\u003e::create({1, 2, 3});\nfor (auto I = a-\u003ebegin(); I.valid(); ++I) {\n  printf(\"%d \", *I);\n} // output: 1 2 3\n\n// Range-based for-loops are supported as well:\nauto a = Array\u003cint\u003e::create({1, 2, 3});\nfor (auto\u0026 v : *a) {\n  printf(\"%d \", v);\n} // output: 1 2 3\n```\n\n### Array\u003cT\u003e::Iterator\nIterator that implements [std::forward_iterator](http://en.cppreference.com/w/cpp/concept/ForwardIterator) with additional functionality described below.\n\nSynopsis:\n\n```cc\nstruct Array\u003cT\u003e::Iterator { // implements std::forward_iterator\n  // is: movable, copyable, move-assignable, copy-assignable, comparable.\n\n  // O(1) distance calculation\n  difference_type distanceTo(const Iterator\u0026 rhs) const;\n\n  // Access value\n  T\u0026              operator*();\n  Value\u003cT\u003e*       value();\n  const Value\u003cT\u003e* value() const;\n\n  // True when this iterator has a value\n  bool valid() const;\n}\n```\n\n## TransientArray\u003cT\u003e\n\nA non-persistent random-accessible ordered collection of value type `T` that provides a subset of the functionality of [Array](#array) but with more efficient modifications, making it suitable for batch updates and modifications. Transient arrays are *not* thread safe.\n\nThe following is a short synopsis instead of full documentation as all the methods listed here are documented under `Array` and work in the same way with the only exception that they mutate the target `TransientArray` rather than returning new arrays.\n\n```cc\nstruct TransientArray\u003cT\u003e {\n  uint32              size() const;\n  ref\u003cTransientArray\u003e push(Value\u003cT\u003e*);\n  ref\u003cTransientArray\u003e push(typename Any\u0026\u0026);\n  ref\u003cTransientArray\u003e set(uint32 i, typename Any\u0026\u0026);\n  ref\u003cTransientArray\u003e set(uint32 i, Value\u003cT\u003e*);\n  const ref\u003cValue\u003cT\u003e\u003e findValue(uint32 i) const;\n  const ref\u003cValue\u003cT\u003e\u003e getValue(uint32 i) const;\n  const T\u0026            get(uint32 i) const;\n  ref\u003cTransientArray\u003e pop();\n  const T\u0026            first() const;\n  const T\u0026            last() const;\n  const ref\u003cValue\u003cT\u003e\u003e firstValue() const;\n  const ref\u003cValue\u003cT\u003e\u003e lastValue() const;\n}\n```\n\nNote that [Array::create](#create--array) is implemented using a transient array for efficient creation, so there should be no need to use TransientArray for trivial array creation.\n\n#### makePersistent() → Array\n\"Seals\" the array and returns a persistent [Array](#array) which refers to the same underlying data.\nReturns null if this transient array is not editable (e.g. `makePersistent()` has already been called.)\n\n```cc\nref\u003cArray\u003cT\u003e\u003e makePersistent();\n\n// Example:\n// acquire Array\u003ct\u003e a in some way...\nauto t = a-\u003easTransient();\n// apply changes to t ...\na = t-\u003emakePersistent(); // =\u003e Array\u003cT\u003e\na = t-\u003emakePersistent(); // =\u003e nullptr -- already sealed and referenced\n```\n\n\n## Value\u003cT\u003e\n\nA reference-counted container for any value. Copying a `Value\u003cT\u003e` does not cause the underlying value to be copied, but instead just referenced in a thread-safe manner.\n\nSynopsis:\n\n```cc\nstruct Value\u003cT\u003e {\n  T value; // value is stored here\n\n  // construct T in-place\n  Value(typename Args\u0026\u0026...);\n\n  // allow implicit cast to T\n  operator T\u0026() { return value; }\n  operator const T\u0026() const { return value; }\n\n  // Value is movable, copyable, move-assignable, copy-assignable, and comparable\n}\n```\n\n## ref\u003cT\u003e\n\nTrivial memory-pointer manager that implements automatic reference counting (thread-safe, intrusive.)\n\nSynopsis:\n\n```cc\nstruct ref\u003cT\u003e {\n  ref();                       // == ref(nullptr)\n  ref(T*);                     // retains a reference\n  ref(const ref\u003cT\u003e\u0026);          // retains a reference\n  ref(ref\u003cT\u003e\u0026\u0026);               // takes over reference\n  ref(const ref\u003ctypename U\u003e\u0026); // retains a reference to U::ptr()\n  ~ref();                      // releases its reference\n\n  // access to T\n  T* ptr() const;\n  operator T*() const;\n  T* operator-\u003e() const;\n\n  ref\u003cT\u003e\u0026 operator=(T*);            // releases its reference, then retains a reference\n  ref\u003cT\u003e\u0026 operator=(const ref\u003cT\u003e\u0026); // releases its reference, then retains a reference\n  ref\u003cT\u003e\u0026 operator=(ref\u003cT\u003e\u0026\u0026);      // releases its reference, then takes over a reference\n  ref\u003cT\u003e\u0026 operator=(const ref\u003ctypename U\u003e\u0026); // like operator=(T*) but gets pointer from U::ptr()\n\n  void swap(T**);     // swap target's pointer with argument's pointer\n  void swap(ref\u003cT\u003e\u0026); // swap target with argument\nprotected:\n  T* _ptr;\n}\n```\n\n`ref` requires `T` to implement the following interface:\n\n```cc\nstruct RefCounted {\n  virtual void retain() const =0;\n  virtual bool release() const =0; // true if count is zero and obj was deleted\n  virtual bool hasSingleRef() const =0;\n};\n```\n\n\n## Learn more\n\nTo learn more about the inner workings of the implementation, consider reading the [\"Understanding Clojure's Persistent Vectors\" series of blog posts](http://hypirion.com/musings/understanding-persistent-vector-pt-1).\n\nTo learn more about the concept of immutable data structures, check out Chris Okasaki's [\"Purely functional data structures\"](https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf).\n\nFor a longer list of functional data structure reading, see [\"New purely functional data structures published since 1998\" on Stack Exchange](http://cstheory.stackexchange.com/questions/1539/whats-new-in-purely-functional-data-structures-since-okasaki#answer-1550).\n\n\n## MIT license\n\nCopyright (c) 2016 Rasmus Andersson \u003chttp://rsms.me/\u003e\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\nall copies 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\nTHE SOFTWARE.\n","funding_links":[],"categories":["TODO scan for Android support in followings","C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Fimmutable-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frsms%2Fimmutable-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frsms%2Fimmutable-cpp/lists"}