The example shows how multiple copy_on_write instances can share the same underlying data until one needs to be modified, at which point a copy is automatically made.
#include <cassert>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
namespace {
class document {
public:
document() = default;
document(const document& other) noexcept = default;
document& operator=(const document& other) noexcept = default;
document(document&& other) noexcept = default;
document& operator=(document&& other) noexcept = default;
using iterator = std::vector<std::string>::const_iterator;
iterator begin()
const {
return _lines.
read().begin(); }
iterator end()
const {
return _lines.
read().end(); }
size_t size()
const {
return _lines.
read().size(); }
bool empty()
const {
return _lines.
read().empty(); }
bool identity(
const document& other)
const {
return _lines.
identity(other._lines); }
void insert(std::string&& line, size_t index) {
assert(index <= size() && "index out of bounds");
[&](const std::vector<std::string>& lines) {
std::vector<std::string> new_lines;
new_lines.reserve((lines.size() + 1) * 2);
new_lines.insert(new_lines.end(), lines.begin(), lines.begin() + index);
new_lines.insert(new_lines.end(), std::move(line));
new_lines.insert(new_lines.end(), lines.begin() + index, lines.end());
return new_lines;
},
[&](std::vector<std::string>& lines) {
lines.insert(lines.begin() + index, std::move(line));
});
}
void erase(size_t index) {
assert(index < size() && "index out of bounds");
[&](const std::vector<std::string>& lines) {
std::vector<std::string> new_lines;
new_lines.reserve((lines.size() - 1) * 2);
new_lines.insert(new_lines.end(), lines.begin(), lines.begin() + index);
new_lines.insert(new_lines.end(), lines.begin() + index + 1, lines.end());
return new_lines;
},
[&](std::vector<std::string>& lines) {
lines.erase(lines.begin() + index);
});
}
};
}
int main() {
cerr << "--- Test starting ---" << endl;
document d0;
d0.insert("Hello, world!", 0);
d0.insert("After Hello", 1);
document d1(d0);
assert(d0.identity(d1));
cerr << "main: calling d1.insert..." << endl;
d1.insert("Start of d1", 0);
cerr << "main: d1.insert returned." << endl;
assert(!d0.identity(d1));
cout << "d0:" << endl;
for (const auto& line : d0) {
cout << line << endl;
}
cout << "d1:" << endl;
for (const auto& line : d1) {
cout << line << endl;
}
cerr << "--- Test finished ---" << endl;
return 0;
}
Definition copy_on_write.hpp:124
Copy-on-write wrapper implementation.
auto identity(const copy_on_write &x) const noexcept -> bool
Returns true if this object and the given object share the same underlying data.
Definition copy_on_write.hpp:342
auto read() const noexcept -> const element_type &
Returns a const reference to the underlying value for read-only access.
Definition copy_on_write.hpp:301
auto write() -> element_type &
Obtains a non-const reference to the underlying value.
Definition copy_on_write.hpp:263
Definition copy_on_write.hpp:111