将仅标头库的包含包装在单个 cpp 文件中

Wrap the includes of a header-only library in a single cpp file

本文关键字:单个 cpp 文件 包装 包含      更新时间:2023-10-16

当我使用像 Boost Spirit 这样的大型仅标题库时,我经常想将其包含隔离到单个 cpp 文件中(parser.cpp), 为了将所需的编译时间减少到只有一个文件。目标是当源文件(main.cpp)需要Spirit设施时, 它可以包含一个头文件,该文件呈现一个引用任何 Spirit 内容的前端类,让这个源文件快速编译。 只有一个 cpp 文件 (parser.cpp) 需要包含 Spirit 标头,并且需要更多时间来编译。

但是,如何创建一个内部需要精神的类,而不在其声明中引用它呢? 我发现的唯一方法是使用指向不完整包装类(QiParser)的指针成员,然后在内部使用newdelete以创建真正的解析器。

我的问题是:有没有更好的方法来做到这一点,而不使用newdelete

这是我现在使用的代码类型:

主.cpp

#include <iostream>
#include "parser.h"
int main (int, char **)
{
Parser p;
int n = 0;
p.parse("78", n);
std::cout << "The parsed number is " << n << std::endl;
return 0;
}

解析器.h

#include <string>
class QiParser; //< Incomplete class declaration
class Parser {
public:
Parser();
~Parser();
bool parse(const std::string &s, int &result) const;
private:
QiParser *qi_parser; //< The only way I found to not include
//  the Spirit headers in this file
};

解析器.cpp

#include "parser.h"
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
// The QiParser class is only present to solve my problem;
// I would like to put this code directly into the Parser class, but without showing
// any Spirit stuff inside the parser.h header file
struct QiParser : qi::grammar<std::string::const_iterator, int()>
{
QiParser() : base_type(start)
{
start %= qi::int_;
}
qi::rule<std::string::const_iterator, int()> start;
};

// Implementation of the Parser class:
Parser::Parser()
{
qi_parser = new QiParser;
}
Parser::~Parser()
{
delete qi_parser;
}
bool Parser::parse(const std::string &s, int &result) const
{
auto iter = s.begin(), end = s.end();
return qi::parse(iter, end, *qi_parser, result);
}

是的,使用std::unique_ptr<QiParser> qi_parser;而不是QiParser * qi_parser;。这被称为 PImpl 习语