2017-10-01 1 views
0
struct A 
{ 
}; 
struct B : A 
{ 
    virtual ~B() {} 
}; 
template<typename BASE, typename EXTENDED> 
void ASSERT_BASE_EXTENDED() 
{ 
    static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error"); 
} 

を持っている私は、基本クラスはEXTENDEDのベースであるかどうかを確認するために、コンパイル時のアサーションを持つ方法を探していますし、彼らが持っているコンパイル同じメモリアドレス。C++そのBASEアサート時間はEXTENDEDの基底クラスで、同じメモリアドレスに

上記の例では、BがAに基づいていても、Aにキャストされると、仮想関数テーブルポインタは実際にはBの最初のメンバーなので、別のメモリアドレスを持ちます。Aが最初のメンバー。

上記の動作はOKですが、VS 2017コンパイラを使用すると「エラーC2131:式が定数に評価されませんでした」というエラーが表示されるため、コンパイル時には動作しません。

"std :: is_base_of"に興味がないのは、同じメモリアドレスのチェックを無視するためです。 これを行う別の方法はありますか?

ありがとうございました

+0

あなたは[_CRTP_](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)と 'static_cast'を使いたいですか? – user0042

+0

CRTPは興味深いコンセプトですが、目的は既存のクラスを変更せず、ASSERT_BASE_EXTENDED機能のみを調整することです。 – Esenthel

答えて

1

メモリアドレスは実行時構成です。その時点では存在しないため、コンパイル時にチェックすることはできません。あなたが言及したキャスティングの種類についても同じことが言えます。それは実行時に完全に起こります。 static_assertをランタイムチェックとエラー処理に置き換える必要があります。 または例外です。

これは、一般的な使用例です。あなたの例のようなハードコーディングされたメモリアドレスの場合、問題はそれらのアドレスintからポインタへのキャストです。これを行う有効な方法は、タイプのTへのポインタが完全に無関係であるため、reinterpret_cast(コンパイラがあなたの例でCスタイルのキャストを試みるキャストの1つ)です。しかし、reinterpret_castはコンパイル時には許可されません。

クランのエラーメッセージがうまくそれを置く:

main.cpp:14:38: note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression 
    static_assert(static_cast<BASE*>((EXTENDED*)256)==(BASE*)256, "error"); 
            ^
+0

私はあなたに同意しません。私のコードをもう一度チェックすると、私は256の定数メモリアドレスからオブジェクトへのポインタを作成していることがわかります。また、dynamic_castとは異なり、コンパイラの値が分かっているメモリオフセットを調整することができます。コンパイラがコンパイル時に行全体を評価するのを妨げるものはありませんが、そうではありません。これらは基本的にコンパイル時の既知の定数の算術演算です。 – Esenthel

+0

私は直感的に質問の簡素化のためにそれらのハードコードされたアドレスを取った。その場合、実際の問題はキャストです。更新された回答を参照してください。 – besc

+0

IMOは、コンパイラが最適化できるものは何でも(事前計算する) - それはすべきです。もしそうなら、それは私の問題を解決するだろう。 – Esenthel

関連する問題