Skip to content

Instantly share code, notes, and snippets.

@saxbophone
Last active July 17, 2022 01:16
Show Gist options
  • Save saxbophone/2b777a80d265654346ac3ee9cb65a625 to your computer and use it in GitHub Desktop.
Save saxbophone/2b777a80d265654346ac3ee9cb65a625 to your computer and use it in GitHub Desktop.
Multivariant --imagine a tagged union that can hold N number of its members at once
#include <cassert>
#include <cstddef>
#include <initializer_list>
#include <tuple>
#include <variant>
template <std::size_t ORDER, typename... Ts>
class multivariant {
std::variant<Ts...> members[ORDER];
public:
// NOTE: non compile-time constraint --values.size() must be ORDER
multivariant& operator=(std::initializer_list<std::variant<Ts...>> values) {
assert(values.size() == ORDER);
// TODO: check precondition: each of the values must have a different type stored!
// NOTE: for this implementation, we could actually store multiple values of the
// same type, however the definition of multivariant doesn't allow this
// because it precludes the reuse of storage by members of other type
// (note that this implementation is not a storage-efficient one)
std::size_t i = 0;
for (auto v : values) {
members[i] = v;
i++;
}
return *this;
}
// NOTE: non compile-time constraint --T must be in Ts
// NOTE: this would ideally be specialised for std::get instead or aswell
template <typename T>
T& get() {
// search for a value of type T
for (std::size_t i = 0; i <= ORDER; i++) {
if (i == ORDER) { assert(false); } // given wrong type!
if (std::holds_alternative<T>(members[i])) {
return std::get<T>(members[i]);
}
}
}
// NOTE: non compile-time constraint --Types must be subset of Ts
// NOTE: this would ideally be specialised for std::get instead or aswell
// NOTE: this one conflicts with the previous definition
// template <typename T, typename... Types>
// std::tuple<Types...> get() {
// return {};
// }
template <typename From, typename To>
multivariant& replace(To value) {
return *this;
}
// read-only iterators to get sequence of stored values?
};
int main() {
multivariant<3, bool, char, int, float, double> f;
f = {true, 'c', 6.54f};
// swap out float for int --TODO: maybe there's a way for us to provide a method for this?
f = {f.get<bool>(), f.get<char>(), 123456};
f.replace<float, int>(123456);
return f.get<int>();
}
multivariant<2, bool, char, int> =
2 * 256 +
2 * 4294967296 +
256 * 4294967296 = 1,108,101,562,880
VERSUS =
3 *
256 * 4294967296 = 3,298,534,883,328
In this case, the first one takes 2.97x fewer values to encode
However, the method that is more efficient to encode depends on the order and the specific size of the types that are used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment