c++11类成员数组大小constexpr正向声明
c++11 class member array size constexpr forward declaration
使用后,我想从包含链中排除一些标头。据我所知,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
下面是问题显而易见的例子。请不要争辩说这不是一个严重的问题。示例被分解以显示最小的抽象语言使用。我将描述老式的解决方案及其缺点。
旧式解决方案
只是另一个标题。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() )
{}
我当前的解决方案
只是另一个标题。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
{}
所以,上面的代码是有效的。其优点是:隐藏复杂性,并且没有运行时动态内存间接寻址。嗯?我的意思是,新的放置允许将整个对象放在堆栈上,并且所有成员地址在编译时都是已知的。我的尝试是在使用不透明指针的接口设计时获得最佳性能。
如果你认为:"这种性能优势不值得思考。"那么请留下这个问题。
我期望的解决方案
只是另一个标题。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
{}
在我当前的解决方案中,我需要验证(bulkywrap_pImpl)的大小并手动调整UNKNOWNSIZE。我认为目前不可能从一个汇编单位向其他单位提供任何信息。我知道这通常是有充分理由的,但这限制了c++11的可能性。
我想指出:
jtc1 sc22 wg21纸张n3337
jtc1 sc22 wg21纸张n3308
请帮我查找天气信息,以及为什么标准不允许这样做。
但此外,我想找到一个解决方案,如何在编译期间将一些文字常量从一个编译单元导出到另一个编译单位。它只是一个文字,所以所有的语句和表达式都不受其影响。因此编译不取决于数组的大小来自哪里。
我的建议为ISO-jtc1-sc22-wg21和编译器开发人员带来了一些工作,但我看不出模板和constexpr之间有任何相关的区别,因为每个定义都必须出现在同一个翻译单元中。这使得模块化编程和干净的接口变得虚假。
不:我不想使用预处理器宏、动态新成员函数或虚拟成员函数。重要的是最大常量正确性,因为类的大小是常量。
请帮助
您不能同时拥有"编译时"answers"来自另一个编译单元"。此外,还不清楚为什么您需要忘记成功解析的头。解析时间已消耗。我建议您创建另一个大小不变的头,从两个文件中都包括它,并将static_assert添加到pimpl文件中,检查constant >= sizeof(pimpl)
。通过编译包括pimpl在内的源文件并执行cout <<sizeof(pimpl)
,您可以将此头作为构建系统的一部分生成。此外,我建议您不要为pimpl指针浪费时间和空间,并将其替换为成员函数,返回正确转换缓冲区的地址。你也没能显示你称皮条客的破坏者在哪里。实现分配/复制/移动/交换也会很有趣
在cpp中使用static_assert检查头中声明的大小>=impl类的大小
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 奇怪的错误 C2131 与 constexpr 声明变量
- 为什么必须将 const 添加到 constexpr 中才能进行字符串文字声明?
- 为什么我不能声明一个 constexpr 本地,而一个 const 一个工作?
- 使用模板参数还包括 constexpr 成员函数enable_if单独定义和声明模板成员函数
- 我可以使用 constexpr 函数声明一个静态数组吗?
- 有没有办法声明一个公共静态常量,该常量将使用 constexpr 在源文件中定义(有什么区别)?
- 是否可以使用"if constexpr"来声明具有不同类型和init-expr的变量
- 无法声明静态 constexpr char []
- 在类外部初始化的 constexpr 静态成员的声明中是否需要 constexpr 说明符
- constexpr:constexpr成员的定义和声明
- 我可以在模板参数中声明一个 constexpr lambda 吗?
- 如果我的班级是字面的班级,那么将我的类的对象声明为constexpr是多余的
- 为什么我不能在类中另一个函数的声明中使用静态 constexpr 的结果?
- 为什么我不能使用 msvc 在模板类中声明静态 constexpr 变量?
- 静态常量声明,变量的constexpr定义,有效的c ++?
- 使用 constexpr 构造函数对结构进行前向声明
- SFINAE 消除、Constexpr 和函数模板:我可以将声明和定义分开吗?
- 模板函数是否以内联方式声明 constexpr,即使实例化不是 constexpr
- 混合constexpr声明和const定义