简体   繁体   English

c ++ 11类成员数组大小constexpr前向声明

[英]c++11 class member array size constexpr forward declaration

I want to exclude some headers from my include chain after having used them. 使用它们后,我想从我的包含链中排除一些头。 From what I know there is no exclude "header.h" in c++11. 据我了解,c ++ 11中没有排除“ header.h”的内容。

Pseudo Code Wishful thinking: 伪代码一厢情愿的想法:

#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

My example where the problem becomes evident follows. 我的问题显而易见的示例如下。 Please don't argue this is not a serious problem. 请不要说这不是一个严重的问题。 The Example is broken down to show the minimal abstract language usage. 细分了该示例以显示最小的抽象语言用法。 I will describe the old fashioned solutions and their disadvantages too. 我还将描述老式的解决方案及其缺点。

Old style solution 旧样式的解决方案

justanotherheader.h: justanotherheader.h:

class bulkywrap
{
public:
    bulkywrap();
protected:
    friend class bulkywrap_pImpl;
    bulkywrap_pImpl *const pImpl; //opaque pointer, private implementation
};

justanothercppunit.cpp: justanothercppunit.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() )
{}

My current Solution 我目前的解决方案

justanotherheader.h: 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
};

justanothercppunit.cpp: justanothercppunit.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
{}

So, the code above is working. 因此,上面的代码正在工作。 The advantages are: hiding complexity and having no runtime dynamic memory indirections. 优点是:隐藏复杂性并且没有运行时动态内存间接。 Huh? ?? I mean, the placement new allows the whole object to be put on stack and all member addresses are known at compile time. 我的意思是,new放置允许将整个对象放入堆栈,并且在编译时知道所有成员地址。 My attempt is to have best performance while using interface design of opaque pointer. 我的尝试是在使用不透明指针的界面设计时获得最佳性能。

If you think: "this performance advantage is not worth the thinking effort." 如果您认为:“这种性能优势不值得您多加考虑。” then please leave that question. 然后请留下那个问题。


My expected Solution 我期望的解决方案

justanotherheader.h: 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
};

justanothercppunit.cpp: justanothercppunit.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
{}

In my current solution I need to verify the sizeof(bulkywrap_pImpl) and adjusting UNKNOWNSIZE manually. 在当前的解决方案中,我需要验证sizeof(bulkywrap_pImpl)并手动调整UNKNOWNSIZE。 I think it is currently not possible to get any information from a compilationunit to others. 我认为,目前不可能从任何编译单元获取任何信息。 I know this is typically intended by good reason, but this limits the possibilities of c++11. 我知道这通常是有充分理由的,但这限制了c ++ 11的可能性。

I want to point out: 我想指出:

jtc1 sc22 wg21 paper n3337 jtc1 sc22 wg21纸n3337

jtc1 sc22 wg21 paper n3308 jtc1 sc22 wg21纸n3308

Please help me to find information weather and why the standard does not allow this. 请帮助我查找天气信息,以及为什么该标准不允许这样做。

But furthermore I would like to find a solution of how to export some literal constant during compiliation time out of a compileunit into another compileunit. 但是,此外,我想找到一种解决方案,该解决方案是在编译期间如何将一些文字常量从一个编译单元中导出到另一个编译单元中。 It's just a literal, so all statements and expressions are not affected by it. 它只是一个文字,因此所有语句和表达式都不受它的影响。 Thus compilation does not depend where the size of the array comes from. 因此,编译不依赖于数组大小的来源。

My suggestion results in some work for the ISO-jtc1-sc22-wg21 and the compiler developers, but I don't see any relevant difference between template and constexpr since every definition must appear in the same translationunit. 我的建议为ISO-jtc1-sc22-wg21和编译器开发人员带来了一些工作,但是我看不到模板和constexpr之间的任何相关区别,因为每个定义都必须出现在相同的翻译单元中。 This makes modular programming and clean interfaces bogus. 这使得模块化编程和干净接口变得虚假。

And no: I don't want to use preprocessor macros, dynamic new or virtual member functions. 不,我不想使用预处理器宏,动态的新成员或虚拟成员函数。 Of importance is maximal const-correctness, since the size of the class is const. 重要的是最大的const正确性,因为类的大小是const。

Please help 请帮忙

you can't have both "compile-time" and "from another compilation unit" at the same time. 您不能同时具有“编译时间”和“来自另一个编译单元”。 also it's not clear why do you need to forget successfully parsed header. 也不清楚为什么您需要忘记成功解析的标头。 parsing time already consumed. 解析时间已消耗。 i suggest you to create another header with size constant, include it from both files, and add static_assert to pimpl file, checking that constant >= sizeof(pimpl) . 我建议您创建另一个具有大小常数的标头,将其包含在两个文件中,然后将static_assert添加到pimpl文件中,检查该constant >= sizeof(pimpl) you can generate this header as part of your build system by compiling source file including pimpl and doing cout <<sizeof(pimpl) . 您可以通过编译包括pimpl的源文件并执行cout <<sizeof(pimpl)来生成此标头作为构建系统的一部分。 also i suggest you to not waste time and space for pimpl pointer and replace it with member function, returning address of properly cast buffer. 我也建议您不要为pimpl指针浪费时间和空间,而应将其替换为成员函数,并返回正确转换缓冲区的地址。 also you failed to show where you call pimpl's destructor. 也没有显示调用pimpl的析构函数的位置。 also implementing assignment/copy/move/swap will be a lot of fun 同时实现分配/复制/移动/交换会很有趣

在cpp中使用static_assert检查在标头中声明的大小> = impl类的大小

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM