【发布时间】:2013-02-19 17:14:10
【问题描述】:
我想在使用后从包含链中排除一些标题。据我所知,c++11 中没有排除“header.h”。
伪代码一厢情愿:
#include "the_bad_header.h" //long includechain with later unused declarations
class bulky { ... };
constexpr std::size_t bulkysize = sizeof(bulky);
forget everything included and class bulky and remember only bulkysize
我的问题变得明显的例子如下。请不要争辩这不是一个严重的问题。该示例被分解以显示最小的抽象语言使用。我将描述老式的解决方案及其缺点。
旧式解决方案
justanotherheader.h:
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
};
只是另一个cppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new bulkywrap_pImpl() )
{}
我目前的解决方案
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
#define UNKNOWNSIZE 12345
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[UNKNOWNSIZE]; //placement new for pImpl
};
只是另一个cppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
所以,上面的代码正在运行。优点是:隐藏复杂性并且没有运行时动态内存间接。嗯?我的意思是,放置 new 允许将整个对象放在堆栈上,并且所有成员地址在编译时都是已知的。我的尝试是在使用不透明指针的界面设计时获得最佳性能。
如果您认为:“这种性能优势不值得思考。”那么请留下这个问题。
我的预期解决方案
justanotherheader.h:
#include "stdint.h" // this is the only header I like to use, but also unnecessary.
constexpr std::size_t get_bulkywrap_pImpl_Size( void ); //constexpr function forward declaration
extern constexpr std::size_t bulkywrap_pImpl_Size; //constexpr literal forward declaration with external initialization
class bulkywrap
{
public:
bulkywrap();
protected:
friend class bulkywrap_pImpl;
bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
uint8_t pImpl_Placement[get_bulkywrap_pImpl_Size()]; //undefined constexpr used
uint8_t pImpl_Placement[bulkywrap_pImpl_Size]; //alternative to above. undefined constexpr used
};
只是另一个cppunit.cpp:
#include "justanotherheader.h"
#include "boost/lotsofheaders.hpp"
//#include more and more headers of highly complex libraries so adding millions of known types and other identifiers, macros, and so on
class bulkywrap_pImpl
{
//lots of members of types used from the other libraries
};
constexpr std::size_t get_bulkywrap_pImpl_Size( void )
{
return sizeof(bulkywrap_pImpl);
}
constexpr std::size_t bulkywrap_pImpl_Size = sizeof(bulkywrap_pImpl);
bulkywrap::bulkywrap()
: pImpl( new(this->pImpl_Placement) bulkywrap_pImpl() ) //using this here is safe
{}
在我当前的解决方案中,我需要验证 sizeof(bulkywrap_pImpl) 并手动调整 UNKNOWNSIZE。 我认为目前无法从编译单元获取任何信息给其他人。我知道这通常是有充分理由的,但这限制了 c++11 的可能性。
我想指出:
请帮我查找信息天气以及为什么标准不允许这样做。
但此外,我想找到一个解决方案,如何在编译期间将一些文字常量从一个编译单元导出到另一个编译单元。它只是一个文字,所以所有的语句和表达式都不受它的影响。因此编译不依赖于数组的大小来自哪里。
我的建议为 ISO-jtc1-sc22-wg21 和编译器开发人员带来了一些工作,但我没有看到模板和 constexpr 之间有任何相关差异,因为每个定义都必须出现在同一个翻译单元中。这使得模块化编程和干净的接口变得虚假。
不:我不想使用预处理器宏、动态 new 或虚拟成员函数。重要的是最大的 const 正确性,因为类的大小是 const。
请帮忙
【问题讨论】:
-
你不能在 C++ 中做到这一点。您需要在构建过程中运行额外的工具。没有什么好害怕的,这个世界(或其中相当大的一部分)是由
configure脚本构建的,它们的作用与您需要的非常相似:构建一个程序,运行它,使用它的输出来构建另一个程序的源代码程序。 -
当然,您的解决方案是合理有效的。我想我需要使用
configure方法。因此,我是否必须编写一个知道隐藏类并输出 interface_configure.h 的主函数?是否有任何可用的库可以获取类头并以类似标准的方式提供文件写入?当然,用 c++ 编写主文件和头文件并不难,但我认为这可以自动改进并与 cmake 和/或 make 结合使用。这些发展战略的关键词是什么。 -
或者请指出一个库,我可以从中学习,但它不应该以过于复杂的方式使用它。
-
也许您出于疑问而将其删减,但您当前的解决方案似乎无法处理对齐。你需要它以及大小。
-
有时我看到一些项目从 cmake/make 创建额外的目标。这些额外的目标运行一些代码,我猜是配置和东西。主要目标取决于这些配置目标,因此必须先构建它们。但现在我不知道如何告诉 cmake 必须在构建主目标之前运行配置目标。 cmake 帮助表示赞赏。
标签: c++ c++11 constexpr placement-new opaque-pointers