I'd like to use boost ptree in my project but since ptree.hpp causes about another 1000 header files to be included this increases compile times drastically (e.g. from 1s to 7s) and as it's needed in over 20 different cpp files this is not acceptable (pre-compiled headers don't improve things much). So I'm thinking of encapsulating the boost ptree in my own class, something like
// myptree.h
#include <boost/property_tree/ptree_fwd.hpp>
class myptree {
private:
boost::property_tree::ptree *m_tree;
public:
...
// adding new (single value) members to the the tree
void put(const std::string&, double);
void put(const std::string&, int);
void put(const std::string&, const std::string&);
// returning (single value) members of the tree
double get_double(const std::string&) const;
int get_int(const std::string&) const;
std::string get_str(const std::string&) const;
// working with subtrees
void push_back(const std::string&, const myptree&);
myptree get_child(const std::string&) const;
// import/export
void read_from_json(const std::string&);
void write_to_json(const std::string&) const;
};
However, I'm failing to implement an iterator in a nice way. Ideally I'd like to have a boost::property_tree::ptree::iterator
as a private member variable which then could be iterated over m_tree
using my own member functions but as I understand from How do I forward declare an inner class? this is general开发者_StackOverflow中文版ly not possible. Any elegant ways of implementing an iterator within this class?
Your problem is a good candidate for the Pimpl idiom, aka compiler firewall, aka Handle-Body. See also this article. The solution you're proposing closely resembles that idiom.
To hide ptree
's iterator from your clients, check out the any_iterator
technique presented in this article.
You can find implementations of any_iterator
here and here.
I don't have a good answer to your actual question, but pre-compiled headers should be a significant improvement in that case. Are you sure it was actually being used and the headers were not still being read from each compilation unit? It can be a little bit tricky to set up optimally. (i.e., avoid the "automatic" option)
Thanks for your answers. Regarding precompiled headers, I checked that they're actually used (g++ -H
shows about 1460 header files originally, and only about 30 when using precompiled headers) and compile time reduced from 7s down to 5.5s which is still not good compared to about 1s when using the above encapsulated class.
Now, when I tried using any_iterator
(which seems to be part of boost now as well) I realised it also added some hundreds of other header files but simply including them didn't increase compile times much. So I tried the same with the ptree header and included ptree.hpp
instead of ptree_fwd.hpp
and that increased compile time by just a bit (from 1.1s to 1.8s). So it seems the heavy compile time penalty comes only when the ptree templates are instantiated? That might also explain why pre-compiled headers didn't help that much? Being lazy and since my main problem was compilation time I might just stick to something like:
// myptree.h
#include <boost/property_tree/ptree.hpp>
class myptree {
private:
boost::property_tree::ptree m_tree;
boost::property_tree::ptree::iterator m_it;
...
};
精彩评论