Skip to content

Instantly share code, notes, and snippets.

@izabera
Last active October 7, 2024 15:57
Show Gist options
  • Save izabera/ae73bc5544a3baf20865ba0f3101ea8f to your computer and use it in GitHub Desktop.
Save izabera/ae73bc5544a3baf20865ba0f3101ea8f to your computer and use it in GitHub Desktop.
basic autovivifying variables in c++, similar to perl/gawk/...
#include <string>
#include <unordered_map>
#include <variant>
template <typename keytype = std::string, typename valtype = std::string>
struct autovivi {
using maptype = std::unordered_map<keytype, autovivi>;
std::variant<std::monostate, valtype, maptype> valueormap;
autovivi() = default;
autovivi& operator=(const valtype& value) {
valueormap = value;
return *this;
}
autovivi& operator[](const keytype& key) {
if (! std::holds_alternative<maptype>(valueormap))
valueormap = maptype{};
return std::get<maptype>(valueormap)[key];
}
operator valtype() const {
if (std::holds_alternative<std::monostate>(valueormap))
return valtype{};
return std::get<valtype>(valueormap);
}
friend std::ostream& operator<<(std::ostream& os, const autovivi& av) {
return os << valtype{av};
}
};
#include <iostream>
int main() {
#define show(...) std::cout << #__VA_ARGS__ " = " << __VA_ARGS__ << '\n';
autovivi var;
var["meow"] = "moo";
var["foo"]["bar"] = "baz";
show(var["meow"]);
show(var["foo"]["bar"]);
show(var["a"]["b"]["c"]);
var["a"]["b"]["c"] = "blah";
show(var["a"]["b"]["c"]);
show(var["a"]["b"]["c"]["d"]);
try {
show(var["a"]["b"]["c"]);
} catch (const std::bad_variant_access& e) {
std::cerr << e.what() << '\n';
}
var["a"]["b"]["c"] = "blah";
show(var["a"]["b"]["c"]);
autovivi<int, int> ints;
ints[2] = 2;
ints[1][2][3][4] = 10;
show(ints[2]);
show(ints[1][2][3][4]);
show(ints[99][17]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment