関数 - C++ライブラリと厳密なエイリアスへのC APIの提供



関数 の 書き方 c++ (1)

厳密なエイリアス違反ではありません。 まず、厳密なエイリアシングは、誤ったタイプのglvalueを介してオブジェクトにアクセスすることです。

あなたの質問では、 LLVMContextを作成し、 LLVMContextアクセスするためにLLVMContext左辺値を使用します。 そこに違法エイリアシングはありません。

起こりうる唯一の問題は、ポインタ変換が同じポインタを返さない場合です。 しかし、これも問題ではありません。なぜなら、 reinterpret_castはラウンドトリップ変換で同じポインタを返すことが保証されているからです。 私たちが元に戻すポインタ型は、データを適切に整列させることです(元の型よりも厳密ではない)。

それが良いか悪いかを問うことは議論の余地があります。 私は個人的にLLVMOpaqueContextを気にせず、 struct LLVMContext*を返します。 それはまだ不透明なポインタであり、型定義がclass間にCヘッダがstructそれを宣言することは重要ではありません。 この2つは型定義のポイントまで交換可能です。

C APIを提供する際の一般的なパターンは、あなたのAPIメソッドに渡されるパブリックヘッダ内のいくつかの不透明な型を宣言してから、翻訳単位内に(したがってC ++の土地に)一度定義したC ++型にreinterpret_castします。

例としてLLVMを使用する:

Types.hこのtypedefが宣言されます:

typedef struct LLVMOpaqueContext *LLVMContextRef;

LLVMOpaqueContextはプロジェクトの他の場所では参照されません。

Core.hでは以下のメソッドが宣言されています:

LLVMContextRef LLVMContextCreate(void);

Core.cppで定義されているCore.cpp

LLVMContextRef LLVMContextCreate() {
  return wrap(new LLVMContext());
}

wrap (およびwrap unwrap )は、 CBindingWrapping.hマクロによって定義されCBindingWrapping.h

#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref)     \
  inline ty *unwrap(ref P) {                            \
    return reinterpret_cast<ty*>(P);                    \
  }                                                     \
                                                        \
  inline ref wrap(const ty *P) {                        \
    return reinterpret_cast<ref>(const_cast<ty*>(P));   \
}

LLVMContext.h使用されていLLVMContext.h

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef)

そこで、C APIは基本的にLLVMOpaqueContextへのポインタをとり、それをllvm::LLVMContextオブジェクトにキャストして、どのメソッドが呼び出されたのかを実行することがllvm::LLVMContextます。

私の質問です:厳密なエイリアシング規則に違反していませんか? そうでない場合は、どうしてですか? もしそうならば、パブリック・インタフェースの境界でこのような抽象化を法的にどのように達成できますか?





strict-aliasing