Last active
July 17, 2022 01:16
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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>(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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