在 C++ 中访问嵌套字典 unordered_map<string, void*>?
Accessing a nested dictionary unordered_map<string, void*> in c++?
假设我们提供了一个嵌套字典,其中的值是字符串或另一个字典,声明为:
unordered_map<string, void*> dictionary
我们如何使用该字典访问和执行操作?
您可能想使用 variant 类型而不是 void*
指针。
所以像这样声明无序映射
struct Map {
std::unordered_map<
std::string,
std::variant<std::unique_ptr<Map>, std::string>
> mp;
};
然后像这样使用它
auto map = Map{};
// insert another map for the key "something"
map.mp["something"] = std::make_unique<Map>();
// insert a string for the key "else"
map.mp["else"] = "whatever";
然后使用这样的映射(使用 C++17),其中 operator<<
为 Map
类型重载
// gotta love structured bindings <3
for (const auto& [key, value] : map) {
std::visit(value, [&key](auto& value) {
cout << key << " : " << value << endl;
}
}
或使用 C++14
for (const auto& key_value : map) {
std::visit(value, [&key_value](auto& value) {
cout << key_value.first << " : " << value << endl;
}
}
如果您无法访问 C++17,那么您仍然可以使用变体的独立实现,例如 boost::variant
等。逻辑和代码看起来惊人地相似
如果由于某种原因给你一个指向 void*
的指针,而你 绝对不能更改 API,你可以使用以下最低限度可行的方法解决方案
struct StringOrAnother {
enum class Type { STRING, MAP };
Type type;
std::unordered_map<std::string, void*> mp;
std::string str;
};
auto mp = std::unordered_map<std::string, void*> mp;
// insert a string
auto val_one = new StringOrAnother{STRING};
val_one.str = "some value";
mp["key one"] = &val_one;
auto val_two = new StringOrAnother{MAP};
mp["key two"] = &val_two;
void print(const std::unordered_map<std::string, void*>& mp) {
for (const auto& key_value : mp) {
cout << key_value.first << " : ";
auto& value = *static_cast<StringOrAnother*>(&key_value.second);
if (value.second.type == StringOrAnother::STRING) {
cout << value.second.str << endl;
} else {
print(value.second.mp);
}
}
}
请注意,我没有使用 unique_ptr
作为指针,而是手动分配了它们。稍后 delete
它们由您决定,而不是泄漏内存!
假设我们提供了一个嵌套字典,其中的值是字符串或另一个字典,声明为:
unordered_map<string, void*> dictionary
我们如何使用该字典访问和执行操作?
您可能想使用 variant 类型而不是 void*
指针。
所以像这样声明无序映射
struct Map {
std::unordered_map<
std::string,
std::variant<std::unique_ptr<Map>, std::string>
> mp;
};
然后像这样使用它
auto map = Map{};
// insert another map for the key "something"
map.mp["something"] = std::make_unique<Map>();
// insert a string for the key "else"
map.mp["else"] = "whatever";
然后使用这样的映射(使用 C++17),其中 operator<<
为 Map
类型重载
// gotta love structured bindings <3
for (const auto& [key, value] : map) {
std::visit(value, [&key](auto& value) {
cout << key << " : " << value << endl;
}
}
或使用 C++14
for (const auto& key_value : map) {
std::visit(value, [&key_value](auto& value) {
cout << key_value.first << " : " << value << endl;
}
}
如果您无法访问 C++17,那么您仍然可以使用变体的独立实现,例如 boost::variant
等。逻辑和代码看起来惊人地相似
如果由于某种原因给你一个指向 void*
的指针,而你 绝对不能更改 API,你可以使用以下最低限度可行的方法解决方案
struct StringOrAnother {
enum class Type { STRING, MAP };
Type type;
std::unordered_map<std::string, void*> mp;
std::string str;
};
auto mp = std::unordered_map<std::string, void*> mp;
// insert a string
auto val_one = new StringOrAnother{STRING};
val_one.str = "some value";
mp["key one"] = &val_one;
auto val_two = new StringOrAnother{MAP};
mp["key two"] = &val_two;
void print(const std::unordered_map<std::string, void*>& mp) {
for (const auto& key_value : mp) {
cout << key_value.first << " : ";
auto& value = *static_cast<StringOrAnother*>(&key_value.second);
if (value.second.type == StringOrAnother::STRING) {
cout << value.second.str << endl;
} else {
print(value.second.mp);
}
}
}
请注意,我没有使用 unique_ptr
作为指针,而是手动分配了它们。稍后 delete
它们由您决定,而不是泄漏内存!