3

Boost 属性树似乎是一个用于解析配置文件的优秀库。但是,我不知道如何处理每个键有多个值的情况。例如,假设我正在指定一个这样的框:

box
{
    x -1 1
    y -1 1
    z -1 1
}

其中xyz分别是框在 、 和 轴上的x边界yz使用 property_tree 的 INFO 格式指定。我在手册中看到使用引号对使用空格的值进行了提及,但是我看不到我可以将这些值作为数字导入。我必须将字符串解析为数字,这似乎首先违背了使用 property_tree 的目的。我当然可以给每个数字一个键:

box 
{
    xlo -1
    xhi 1
    ylo -1
    yhi 1
    zlo -1
    zhi 1
}    

但这似乎很麻烦,并且会膨胀我的配置文件。我还注意到我可以在 program_options 中处理这种情况,但是我失去了嵌套配置文件的功能(是的,我知道我可以使用点符号来“嵌套”,但它不一样)。

有没有办法将例如 x 作为这样的数字列表导入?

4

1 回答 1

5

标准的 property_tree 每个键只处理一个字符串值,因为它被定义为:

typedef basic_ptree<std::string, std::string> ptree;

因此,唯一的选择是使用字符串并解析它们。我认为最好的方法是定义一个新的类来存储低值和高值,然后为 get 和 set 方法创建一个转换器类。例如:

struct low_high_value
{
  low_high_value() : m_low(0), m_high(0) { }
  low_high_value(double low, double high) : m_low(low), m_high(high) { }
  double m_low;
  double m_high;
};

翻译者将是:

struct low_high_value_translator
{
  typedef std::string    internal_type;
  typedef low_high_value external_type;
  // Get a low_high_value from a string
  boost::optional<external_type> get_value(const internal_type& str)
  {
    if (!str.empty())
    {
      low_high_value val;
      std::stringstream s(str);
      s >> val.m_high >> val.m_low;
      return boost::optional<external_type>(val);
    }
    else
      return boost::optional<external_type>(boost::none);
  }

  // Create a string from a low_high_value
  boost::optional<internal_type> put_value(const external_type& b)
  {
    std::stringstream ss;
    ss << b.m_low << " " << b.m_high;
    return boost::optional<internal_type>(ss.str());
  }
};

前面的get_value方法很简单。如果文件可以由用户写入,则应该改进。

此类应使用以下方式注册:

namespace boost { namespace property_tree 
{
  template<typename Ch, typename Traits, typename Alloc> 
  struct translator_between<std::basic_string< Ch, Traits, Alloc >, low_high_value>
  {
    typedef low_high_value_translator type;
  };
} }

包含前面的代码后,您可以将 property_tree 用作:

  pt.get<low_high_value>("box.x")
  pt.put("box.u", low_high_value(-110, 200));
于 2012-10-27T23:44:00.480 回答