如何转发声明boost :: ptree :: iterator

时间:2011-05-11 21:35:24

标签: c++ boost forward-declaration boost-propertytree

我想在我的项目中使用boost ptree,但是由于ptree.hpp导致包含另外1000个头文件,这大大增加了编译时间(例如从1s到7s)并且需要超过20个不同的cpp文件这是不可接受的(预编译的标题不会改善很多东西)。所以我想在我自己的类中封装boost ptree,比如

// 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;

};

但是,我没能以一种很好的方式实现迭代器。理想情况下,我希望将boost::property_tree::ptree::iterator作为私有成员变量,然后可以使用我自己的成员函数在m_tree上进行迭代,但据我所知How do I forward declare an inner class?,这通常是不可能的。在这个类中实现迭代器的任何优雅方法?

3 个答案:

答案 0 :(得分:4)

您的问题是Pimpl idiom,又名编译器防火墙,又名 Handle-Body 的理想选择。另见article。你提出的解决方案非常类似于成语。

要隐藏客户端的ptree迭代器,请查看this article中提供的any_iterator技术。

您可以找到any_iterator herehere的实现。

答案 1 :(得分:3)

我对您的实际问题没有一个好的答案,但预编译的标题应该在这种情况下是一个重大改进。你确定它实际上正在使用,并且仍然没有从每个编译单元读取标题吗?设置最佳可能有点棘手。 (即避免使用“自动”选项)

答案 2 :(得分:0)

感谢您的回答。关于预编译头文件,我检查了它们实际使用过(g++ -H最初显示了大约1460个头文件,使用预编译头文件时只显示了大约30个)并且编译时间从7s减少到5.5s,这仍然不是很好使用上述封装类时大约为1秒。

现在,当我尝试使用any_iterator(现在似乎也是提升的一部分)时,我意识到它还添加了数百个其他头文件,但只是包含它们并没有增加编译时间。所以我尝试使用ptree头并使用ptree.hpp代替ptree_fwd.hpp,并且将编译时间增加了一点(从1.1s增加到1.8s)。因此,只有在实例化ptree模板时才会出现繁重的编译时间惩罚?这也可以解释为什么预编译的标题没有那么多帮助?懒惰,因为我的主要问题是编译时间,我可能只会坚持:

// myptree.h
#include <boost/property_tree/ptree.hpp>

class myptree {
   private:
      boost::property_tree::ptree           m_tree;
      boost::property_tree::ptree::iterator m_it;
   ...
};