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 <string>
#include <vector>
using namespace std;
using namespace stlab;
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 = lines;
new_lines.insert(new_lines.begin() + index, std::move(line));
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 = lines;
if (index < lines.size()) {
new_lines.erase(new_lines.begin() + index);
}
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;
}
auto identity(const copy_on_write &x) const noexcept -> bool
auto read() const noexcept -> const element_type &
auto write() -> element_type &
Copy-on-write wrapper implementation.