このマニュアルの他の箇所(ExportKey)で、BOOST_CLASS_EXPORT
を解説しています。Exportは2つのことを意味します。
- 他で参照されないコードをインスタンス化します。
- シリアライズのために、external識別子とクラスを対応づけます。クラスが明示的に参照されないという事実は、この必要条件を示します。
C++では、明示的に参照されないコードは、仮想関数によって実装されます。よって、派生クラスを基底クラスのポインタまたは参照経由で操作するような用法の場合、exoprtが必要であることを意味します。
任意のアーカイブクラスのヘッダをインクスードするのと同じソースモジュールにあるBOOST_CLASS_EXPORT
は、それらアーカイブクラスにポリモーフィックなポインタのシリアライズを要求するコードをインスタンス化します。
アーカイブクラスのヘッダが(BOOST_CLASS_EXPORT
しているソースに)含まれないならば、どんなコードもインスタンス化されません。
BOOST_CLASS_EXPORT
は、アーカイブクラスのインクルードよりもあとに配置する必要があります。
BOOST_CLASS_EXPORT
を使うコードは、以下のようになります
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
... // other archives
#include "a.hpp" // header declaration for class a
BOOST_CLASS_EXPORT(a)
... // other class headers and exports
これは、スタンドアロンな実行ファイルや、スタティックライブラリ、ダイナミックまたはsharedライブラリであるかどうかに関係しません。
"a.hpp"
でBOOST_CLASS_EXPORT
をインクルードすることは、アーカイブヘッダをBOOST_CLASS_EXPORT
よりも前にインクルードするという上記のルールに従うことを、困難にするまたは不可能にします。
このようなことが行いたい場合、ヘッダファイルの宣言にてBOOST_CLASS_EXPORT_KEY
を用い、クラス定義を行うファイルでBOOST_CLASS_EXPORT_IMPLEMENT
を用いることでうまく解決できます。
この仕組みは、コードをスタティックまたはsharedライブラリに置くことを考慮しています。
アーカイブクラスのヘッダも合わせてインクルードしない限り、ライブラリコードにBOOST_CLASS_EXPORT
を配置しても効果はありません。
そんなわけで、ライブラリを作る際は、利用者が期待するすべてのアーカイブクラスのためのヘッダをインクルードしなければなりません。
あるいは、ポリモーフィックなアーカイブのためだけに、ヘッダファイルをインクルードすることができます。
厳密に言えば、すべてのポインタ経由のシリアライズが、もっとも派生したクラスによって発生するならば、exportは必要ではありません。
しかし、何が破壊的なエラーかを見つけるために、ライブラリはすべてのポインタ経由のポリモーフィックなシリアライズをトラップします。対象クラスが、exportされない、あるいは、登録されていないとしても。
現実には、ポインタ経由でシリアライズする1つまたはそれ以上の仮想関数を持つクラスをすべて登録またはexportします。
この機能の実現が、C++のベンダー拡張に依存することに注意してください。しかし、boostでテスとされるすべてのC++コンパイラは、要求された拡張を提供します。ライブラリは、それぞれのコンパイラで必要となる追加の宣言を含みます。将来C++コンパイラがこれらの拡張か、それと等価な何かをサポートするという予想は合理的と言えます。