The Cow Class: A Copy-On-Write C++ Template






4.74/5 (9 votes)
Copy your objects only when needed
This is part of my multithreading library at github, here.
Code
template <typename T> class cow { private: mutable std::shared_ptr<T> t; public: template< typename ...Args> cow(Args ... args) { t = std::make_shared<T>(args...); } cow(std::shared_ptr<T> t2) { t = t2; } operator const std::shared_ptr<T>() const { return t; } const T operator *() { return *t; } // Write shared_ptr<T> operator ->() { if (t.use_count() == 1) return t; std::shared_ptr<T> t2 = std::make_shared<T>(*t); t = t2; return t; } void write(std::function<void(std::shared_ptr<T> )> f) { f(operator ->()); } };
You have the object to be manipulated in a shared_ptr<> form. The class constructor's take either an existing pointer or they can construct a new object with the aid of variadic template functions.
When using this class to read data, nothing happens:
struct FOO { int a1 = 0; int a2 = 0; }; std::shared_ptr<FOO> x = std::make_shared<FOO>(); cow<FOO> c1(x); // gets the pointer const FOO& j1 = *c1; cow<FOO> c2 = c1;
All the above is serviced through the const operator/const T* cast functions.
When writing the data, the class duplicates the pointer before writing to it:
c1->a2 = 2; // 1 copy
Now c1 does not anymore contain the same as the original x, which remains untouched.
c1->a4 = 2; // No copy
There should be another copy but the previous one dissappears because it had a ref of 1, so it's all optimized out.
c2.write([](std::shared_ptr<FOO> t) { t->a1 = 10; t->a2 = 20; });
This would allow you to write once without creating uneccesary copies.
Have fun using it!
History
9 - 2 - 2020: First release