Angelo
Angelo

Reputation: 51

boost property_tree issues getting values

This is my first experience with boost::property_tree and I can't find a way to reproduce the way to get values from a tree following the documentation (How to Access Data in a Property Tree). This is the simple code that I wrote to experiment with a property tree:

#include <iostream>
#include <string>

#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/ptree.hpp>

namespace pt = boost::property_tree;

int main(int argc, char *argv[]) {
  pt::ptree tree;

  tree.put("pi", 3.14159);
  tree.put("name", "John Doe");

  for (auto &[key, value] : tree)
    std::cout << key << " : " << value.get_value<std::string>() << "\n";

  std::cout << "pi : " << tree.get_value("pi") << "\n";
  std::cout << "name : " << tree.get_value("name") << "\n";

  auto pi = tree.get_optional<float>("pi").get();
  std::cout << "pi optional : " << pi << "\n";

  auto pi_found = tree.find("pi");
  std::cout << "pi found : " << pi_found->second.data() << "\n";

  // the commented line doesn't compile
  // std::cout << "not found : " << tree.get_value<int>("null") << "\n";

  std::cout << "not found : " << tree.get_value("null") << "\n";

  // the line below causes an assertion error:
  // Assertion failed: (this->is_initialized()), function get, file /usr/local/include/boost/optional/optional.hpp, line 1191.
  // not found : Abort trap: 6
  std::cout << "not found : " << tree.get_optional<int>("null").get() << "\n";

  pt::write_info("ptree.info", tree);

  return 0;
}

This is the output:

pi : 3.1415899999999999
name : John Doe
pi :
name :
pi optional : 3.14159
pi found : 3.1415899999999999
not found :

As can be seen tree.get_value("whatever") returns no value, tree.get_value("null") does not throw an exception and get_optional<whatever type> does not compile. My experiment behaves way too different from the stated in the documentation. Excluding the line that causes the assertion error creates the output info file as expected.

My environment is:

MacOS 10.11.6
macbrew installed tools and libraries
boost 1.67
clang 7.0
meson build system

Upvotes: 1

Views: 4088

Answers (2)

Angelo
Angelo

Reputation: 51

My bad, instead of using tree.get<float>("pi") I copied and pasted tree.get_value<float>("pi") that is meant for a different use. The question is answered with the help of @rafix07 comment. The get<type>("key path") is the correct method to use.

Upvotes: 0

rafix07
rafix07

Reputation: 20938

You can draw your ptree as:

node1 is tree (has 2 children, data() of tree is "")
 |
 |- (node2) pi ----> data=3.14...
 |
 |- (node3) name --> data="Joe Doe"

[1]

As can be seen tree.get_value("whatever") returns no value

tree is node and has 2 children (pi, name). While calling

tree.get_value(defaultValue) // you are not passing PATH, but DEFAULT VALUE

above line is translated into

tree.get_child("").get_value(defaultValue)

so, "" path exists because it is path to tree node, and tree.data() returns "" - empty string for this path. So defaultValue cannot be printed and you see empty string as output. You should call get_value only for children (use get_child on tree before calling this methid, it is described in boost reference), and parameter of get_value is default value. So replace

  std::cout << "pi : " << tree.get_child("pi").get_value("PI is 4.0") << "\n";
  std::cout << "name : " << tree.get_child("name").get_value("noname") << "\n";

you will see 3.14 and Joe Doe.

[2]

tree.get_value("null") does not throw an exception

is was described in [1] point. "" path exists, and data() for this path is empty string. So you cannot see null string as default value.

[3]

// the commented line doesn't compile // std::cout << "not found : "

<< tree.get_value("null") << "\n";

This line cannot be compiled because ptree class doesn't have that method, I suppose you want to call this method:

  template<typename Type> 
  unspecified get_value(const Type & default_value) const;

you defined Type as int, int as function template parameter involves that default value can be only int, not string.

Upvotes: 1

Related Questions