Boost property_tree: несколько значений на ключ

Дерево свойств Boost выглядит как отличная библиотека для разбора конфигурационных файлов. Тем не менее, я не могу понять, как обрабатывать ситуации, когда существует несколько значений на ключ. Например, допустим, я указывал поле вроде этого:

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

гдеx, y, а такжеz границы коробки наx, y, а такжеz оси соответственно, указанные с использованием формата INFO property_tree. Я вижу упоминание в руководстве об использовании кавычек для значений, которые используют пробелы, но потом я не вижу, что я мог бы импортировать эти значения в виде чисел. Я должен был бы разобрать строку в числа, что, кажется, побеждает цель использования property_tree в первую очередь. Я, конечно, мог бы дать каждому числу ключ:

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

но это кажется громоздким и раздувает мой конфигурационный файл. Я также отметил, что могу справиться с этой ситуацией в program_options, но я теряю возможности вложенного файла конфигурации (да, я знаю, что могу использовать точечную нотацию для «вложения», но это не то же самое).

Есть ли способ импортировать, например, х как список чисел, как это?

Ответы на вопрос(1)

Решение Вопроса
,

значение на ключ, поскольку оно определяется как:

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));
 J. Calleja26 мая 2015 г., 14:44
@Napseis Можно расширить это для вектора. Вы должны шаблонизировать класс low_high_value_translator для векторного значения. Я не уверен в параметре dim template, потому что векторное измерение должно контролироваться переводчиком на основе строковых данных.
 Napseis22 апр. 2015 г., 16:06
Можно ли расширить это для случая, когда low_high_value - это std :: vector вместо этого, и мы используем шаблон <int dim> в Translator, чтобы сделать размер val.resize (dim), пожалуйста? Спасибо
 Napseis22 апр. 2015 г., 15:53
спасибо за этот совет. У меня были проблемы с этим, пока я не понял, что type_f internal_type и external_type важны, имя не должно быть изменено

Ваш ответ на вопрос