在c ++中访问嵌套字典unordered_map <string,void * =“”>?

时间:2017-06-28 17:43:59

标签: c++ c++11 dictionary void-pointers unordered-map

假设我们提供了一个嵌套字典,其中的值是字符串或另一个字典,声明为:

unordered_map<string, void*> dictionary

我们如何使用此词典访问和执行操作?

1 个答案:

答案 0 :(得分:3)

您可能希望使用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取决于它们而不是泄漏记忆!