Skip to content

Instantly share code, notes, and snippets.

@camila314
Created January 12, 2026 15:14
Show Gist options
  • Select an option

  • Save camila314/180d6dc0afbc0abd581ef466f2b69bc3 to your computer and use it in GitHub Desktop.

Select an option

Save camila314/180d6dc0afbc0abd581ef466f2b69bc3 to your computer and use it in GitHub Desktop.
CoW for c++20
#include <concepts>
template <std::copy_constructible T>
class cow {
std::shared_ptr<T> data;
void clone() {
data = std::make_shared<T>(*data);
}
public:
cow(cow const& c) : data(c.data) {}
cow(cow&& c) : data(std::move(c.data)) {}
cow(T const& t) : data(std::make_shared<T>(t)) {}
template <typename ...Args> requires std::constructible_from<T, Args...>
cow(Args... args) : data(std::make_shared<T>(std::forward<Args>(args)...)) {}
cow(T&& t) : data(std::make_shared<T>(std::move(t))) {}
template <typename Q> requires requires(T a, Q b) { a = b; }
cow& operator=(Q&& t) {
clone();
*data = std::forward<Q>(t);
return *this;
}
#define OPS(op) \
auto operator op(T&& t) const { return (*data) op std::move(t); } \
auto operator op(T const& t) const { return (*data) op t; } \
auto operator op(cow const& t) const { return (*data) op (*t.data); } \
OPS(+) OPS(-) OPS(*) OPS(/) OPS(%) OPS(<=>) OPS(<<) OPS(>>) OPS(&) OPS(|)
#undef OPS
#define OPS(op) \
cow& operator op(T&& t) { clone(); (*data) op std::move(t); return *this; } \
cow& operator op(T const& t) { clone(); (*data) op t; return *this; } \
cow& operator op(cow const& t) { clone(); (*data) op (*t.data); return *this; }
OPS(+=) OPS(-=) OPS(*=) OPS(/=) OPS(%=) OPS(<<=) OPS(>>=) OPS(&=) OPS(|=)
#undef OPS
cow& operator++() {
clone();
(*data)++;
return *this;
}
cow& operator--() {
clone();
(*data)--;
return *this;
}
operator T() const {
return *data;
}
operator T const&() const {
return *data;
}
operator T&() {
clone();
return *data;
}
std::shared_ptr<T> const ptr() const {
return data;
}
T const& inner() const {
return *data;
}
bool operator==(cow const&) const = default;
bool operator==(T const& t) const {
return (*data) == t;
}
bool operator==(T&& t) const {
return (*data) == std::move(t);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment