'Nested initializer lists
I am making an attempt in creating dynamic Python-like dicts in C++. One possible approach to implementation (which has its drawbacks, for sure) is
#include <iostream>
#include <variant>
#include <map>
using namespace std;
class dict;
using Atom = variant<bool, int, double, string, dict>;
class dict {
map<string, Atom> data_;
public:
template<typename T>
bool put(const string& k, T&& v) {
data_[k] = std::forward<T&&>(v);
return true;
}
template<typename T>
T& get(const string& k) {
return std::get<T>(data_[k]);
}
template<class T>
bool contains(T&& k) {
return data_.find(std::forward<T&&>(k)) != data_.end();
}
dict(initializer_list<pair<string, Atom>> kvs) {
for (auto kv : kvs) (this->put(kv.first, kv.second));
}
};
Now consider this last variadic initializer. The thing is, it is not exactly as flexible as I would want it to be:
int main() {
// This works:
auto u = dict{
{"a", 9},
{"b", 1.2},
{"c", true},
{"d", dict{
{"e", "f"}
}}
};
// This does not:
auto v = dict{
{"a", 9},
{"b", 1.2},
{"c", true},
{"d", {
{"e", "f"}
}}
};
return 0;
}
The question is, how does one rewrite this so that the necessary initializer lists would be automatically cast to pair<string, Atom>?
Solution 1:[1]
Thanks to @Jarod42, I have managed to come up with this:
#include <iostream>
#include <variant>
#include <map>
#include <cassert>
using namespace std;
class dict;
class Atom;
class dict {
map<string, Atom> data_;
public:
template<typename T>
bool put(const string& k, T&& v) {
data_[k] = std::forward<T&&>(v);
return true;
}
template<typename T>
T& get(const string& k) {
return std::get<T>(data_[k]);
}
template<class T>
bool contains(T&& k) {
return data_.find(std::forward<T&&>(k)) != data_.end();
}
dict(std::initializer_list<pair<string, Atom>> kvs);
};
using AtomBase = variant<bool, long, double, string, dict>;
class Atom : public AtomBase {
using AtomBase::AtomBase;
public:
Atom(initializer_list<pair<string, Atom>> l) {
*this = dict(l);
}
};
dict::dict(std::initializer_list<pair<string, Atom>> kvs) {
for (auto kv : kvs) {
this->put(kv.first, kv.second);
}
}
int main() {
[[maybe_unused]]
auto u = dict{
{"a", 9},
{"b", 1.2},
{"c", true},
{"d", {
{"e", "f"}
}}
};
return 0;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mike Land |
