4

いくつかのヘッダーを、使用後にインクルード チェーンから除外したいと考えています。私が知っていることから、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
};

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() )
{}

私の現在の解決策

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:

#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
};

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
{}

私の現在のソリューションでは、sizeof(bulkywrap_pImpl) を確認し、UNKNOWNSIZE を手動で調整する必要があります。現在、編集ユニットから他のユニットに情報を取得することはできないと思います。これは通常、正当な理由で意図されていることを知っていますが、これにより c++11 の可能性が制限されます。

私は指摘したい:

jtc1 sc22 wg21 紙 n3337

jtc1 sc22 wg21 紙 n3308

情報天気と、標準でこれが許可されていない理由を見つけるのを手伝ってください。

しかしさらに、コンパイル時にリテラル定数をコンパイルユニットから別のコンパイルユニットにエクスポートする方法の解決策を見つけたいと思います。これは単なるリテラルであるため、すべてのステートメントと式は影響を受けません。したがって、コンパイルは配列のサイズがどこから来るかに依存しません。

私の提案は、ISO-jtc1-sc22-wg21 とコンパイラの開発者にいくらかの作業をもたらしますが、すべての定義が同じ変換単位に表示される必要があるため、テンプレートと constexpr の間に関連する違いは見られません。これにより、モジュラー プログラミングとクリーンなインターフェイスが偽物になります。

いいえ: プリプロセッサ マクロ、動的な新しいメンバー関数または仮想メンバー関数を使用したくありません。クラスのサイズは const であるため、最大の const-correctness が重要です。

助けてください

4

2 に答える 2

2

「コンパイル時」と「別のコンパイル単位から」の両方を同時に持つことはできません。また、正常に解析されたヘッダーを忘れる必要がある理由も明確ではありません。解析時間はすでに消費されています。サイズが一定の別のヘッダーを作成し、両方のファイルからインクルードし、pimpl ファイルに static_assert を追加して、それを確認することをお勧めしますconstant >= sizeof(pimpl)。pimpl を含むソース ファイルをコンパイルしてcout <<sizeof(pimpl). また、pimplポインターの時間とスペースを無駄にせず、適切にキャストされたバッファーのアドレスを返すメンバー関数に置き換えることをお勧めします。また、pimpl のデストラクタを呼び出す場所を示すことができませんでした。また、割り当て/コピー/移動/スワップの実装もとても楽しいでしょう

于 2013-02-20T13:24:29.530 に答える