Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting STL Map from Boost Property Tree

Tags:

c++

stl

boost

I understand that boost::property_tree::ptree may contain key-value pairs where the 'value' may be of any type. Now my question is that, now my 'value' is a std::map, and when I attempt to pt.get<std::map<std::string, std::string>> where pt is a property tree, I get a compile time error. Hence, my question is:

How to extract a STL map value from a boost property tree? If this is not possible, is there any way of converting between STL map and boost property tree (so that each node of the property tree is not a STL container but a simple data type).

like image 405
RelativisticPenguin Avatar asked Dec 20 '25 12:12

RelativisticPenguin


1 Answers

Very simply:

Live On Coliru

ptree pt;

std::map<std::string, ptree> m(pt.begin(), pt.end());

However, note that keys need not be unique:

std::multimap<std::string, ptree> mm(pt.begin(), pt.end());

And if you are want to transform all values to std::string (assuming they all have a string value):

std::map<std::string, std::string> dict;
for (auto& [k,v]: pt) {
    dict.emplace(k, v.get_value<std::string>());
}

Side-By-Side Comparisoon

Live On Compiler Explorer

#include <boost/property_tree/ptree.hpp>
#include <map>
#include <fmt/ranges.h>
using boost::property_tree::ptree;

template<> struct fmt::formatter<ptree> : fmt::formatter<std::string>
{
    template<typename Ctx>
    auto format(ptree const& pt, Ctx& ctx) {
        return format_to(ctx.out(), "'{}'", pt.get_value<std::string>());
    }
};

int main() {
    ptree pt;
    pt.put("keyA", "valueA-1");
    pt.put("keyB", "valueB");
    pt.put("keyC", "valueC");

    pt.add("keyA", "valueA-2"); // not replacing same key
    
    std::map<std::string, ptree> m(pt.begin(), pt.end());
    std::multimap<std::string, ptree> mm(pt.begin(), pt.end());

    std::map<std::string, std::string> dict;
    for (auto& [k,v]: pt) {
        dict.emplace(k, v.get_value<std::string>());
    }

    fmt::print(
        "map:\n\t{}\n"
        "multimap:\n\t{}\n"
        "dict:\n\t{}\n",
        fmt::join(m, "\n\t"),
        fmt::join(mm, "\n\t"),
        fmt::join(dict, "\n\t")
    );
}

Prints

map: 
        ("keyA", 'valueA-1')
        ("keyB", 'valueB')
        ("keyC", 'valueC')
multimap:
        ("keyA", 'valueA-1')
        ("keyA", 'valueA-2')
        ("keyB", 'valueB')
        ("keyC", 'valueC')
dict:
        ("keyA", "valueA-1")
        ("keyB", "valueB")
        ("keyC", "valueC")

BONUS: Ptree From String Dictionary

added ptree_from_map function

template <typename MapLike>
ptree ptree_from_map(MapLike const& m) {
    ptree pt;
    for (auto const& [k,v]: m) {
        pt.add(k, v);
    }
    return pt;
}
like image 103
sehe Avatar answered Dec 22 '25 03:12

sehe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!