где boost property_tree::empty_ptree?

Я использую библиотеку property_tree для ботинок. Я ищу способ получить дочерний узел из объекта ptree, но вернуть пустой ptree в случае неудачи. Я наткнулся на хороший пример в property_tree/examples/empty_ptree_trick.cpp:

void process_settings(const std::string &filename)
{
    ptree pt;
    read_info(filename, pt);    
    const ptree &settings = pt.get_child("settings", empty_ptree<ptree>());
    std::cout << "\n    Processing " << filename << std::endl;
    std::cout << "        Setting 1 is " << settings.get("setting1", 0) << std::endl;
    std::cout << "        Setting 2 is " << settings.get("setting2", 0.0) << std::endl;
    std::cout << "        Setting 3 is " << settings.get("setting3", "default") <<     std::endl;
}

который делает именно то, что мне нужно. Проблема в том, что компилятор жалуется, что функция empty_ptree() не является членом boost:property_tree. Есть идеи, где empty_ptree()?

Я использую Boost 1.44 на VS2010.


person bavaza    schedule 15.02.2011    source источник


Ответы (2)


Я только что потратил целый день, пытаясь ответить на этот вопрос!

Это было моим решением. Во-первых, я использовал указатели, а не ссылки, так как их нужно сразу инициализировать. Затем я просто поймал исключение и добавил новое ptree.

using namespace boost::property_tree;

ptree r_pt;
ptree *c_pt;

read_xml( "file.xml" , r_pt);

try {
    c_pt = &(r_pt.get_child( "example" ));
}
catch (ptree_bad_path) {
    c_pt = &(r_pt.put_child( "example", ptree() ));
}

std::cout << "Setting 1 is " << c_pt.get("setting1", 0) << std::endl;

Насколько я понял, они ожидают, что мы будем использовать тип boost::Optional. Но я только начинающий..

EDIT Я только что нашел реализацию empty_ptree‹>.

template<class Ptree>
    inline const Ptree &empty_ptree()
    {
        static Ptree pt;
        return pt;
    }

Я думаю, вы можете просто добавить это в свой код и использовать его, как описано в empty_ptree_trick.cpp, но пока я придерживаюсь своего решения, пока не узнаю, как это на самом деле должно быть сделано.

person expelledboy    schedule 04.03.2011
comment
@expelleboy - спасибо за старания :-). Однако есть несколько проблем с предложенным вами кодом: 1) read_xml также может вызывать ошибки, поэтому вы можете поместить его в блок try. 2) Я не уверен, какова продолжительность жизни ptree, возвращаемого get_child, однако примеры в boost всегда присваивают результат из get‹› и никогда не берут их адрес. Вы можете получить висячий указатель. 3) вы можете пропустить try-catch, так как необязательная версия get‹› (та, что используется в вашем блоке catch), никогда не выбрасывает. 4) Более эффективно возвращать ссылку на empty_ptree, чем создавать его. - person bavaza; 06.03.2011
comment
@bavaza нп. На самом деле я решил эти проблемы, создав класс (xml_branch в моем коде), который я унаследовал, что заставляет меня создавать экземпляры только внутри класса, который наследует xml_branch, или указатель на ptree. Затем корневой класс имеет фактическое ptree и его указатель. Затем root обрабатывает все исключения, возникающие при инициализации элемента xml_branch. К сожалению, я не могу показать вам полный исходный код, но могу сказать, что это довольно элегантный способ сделать это. - person expelledboy; 07.03.2011
comment
Извините, я хотел сказать, что ветка обрабатывает все исключения, но я не могу отредактировать свой комментарий. - person expelledboy; 07.03.2011
comment
Мне также очень любопытно, где empty_ptree в boost.org Источник /doc/libs/1_55_0/libs/property_tree/examples/! - person Ela782; 06.12.2013
comment
Хорошо, @expelledboy, ты нашел реализацию -- но в каком файле? Когда я grep 'empty_ptree' -r в моем $BOOST_ROOT есть 11 обращений - большинство из них являются комментариями или документацией, ни одно из них не является фактической реализацией. - person Christian Severin; 12.07.2017

void process_settings(const std::string &filename)
{
    ptree pt;
    read_info(filename, pt);    
    const ptree &settings = pt.get_child("settings", ptree());
    std::cout << "\n    Processing " << filename << std::endl;
    std::cout << "        Setting 1 is " << settings.get("setting1", 0) << std::endl;
    std::cout << "        Setting 2 is " << settings.get("setting2", 0.0) << std::endl;
    std::cout << "        Setting 3 is " << settings.get("setting3", "default") <<     std::endl;
}

Обратите внимание, что это предотвратит создание экземпляра boost::wrapexceptboost::property_tree::ptree_bad_path.

person Edward Kigwana    schedule 01.12.2020