2

データ メンバーのオフセットは、次のように簡単に取得できます。

#define MEMBER_OFFSET(Type, Member) \
    ((unsigned long)(((char *)&((Type *)0)->Member) - (char *)0));

これをコンパイル時の定数式にしたい (または型特性を使用したい)。たとえば、メンバー オフセットを使用して SFINAE ベースのソリューションを実装するために使用するには、静的アサーションなどを使用します。

更新:問題は、コンパイル時の式にする方法です。POD 型で動作するかどうか、または C ライブラリなどに標準マクロがあるかどうかではありません。

4

3 に答える 3

3

コンパイラが何であるかはわかりませんが、次のコードはVC8、ideone(gcc-4.3.4)、およびComeauオンラインでコンパイルできます。

struct A { int i; };
template< size_t > struct S;

int main() {
  S< offsetof( A, i ) > *p;
}

Gccには__offsetof__拡張子があります。VCには、奇妙なことに、テンプレート引数の非コンパイル時定数を取得する機能があるようです。offsetof コモーに関しては、残念ながらコモーの内部についてはわかりません。

ちなみに、これでは直接質問に答えることはできませんが、SFINAEの目的では、メンバーポインタ定数をテンプレート引数として使用でき、それに特化できるため、次のように記述できます。

struct A {
  int i, j;
};

template< int A::* > struct S;
template<> struct S< &A::i > { static char const value = 'i'; };
template<> struct S< &A::j > { static char const value = 'j'; };

int main() {
  cout<< S< &A::i >::value <<endl;
  cout<< S< &A::j >::value <<endl;
}

お役に立てれば。

于 2011-02-04T18:52:29.317 に答える
1

C標準ライブラリoffsetofには、これが試みていることを行うものがすでにあります(ただし、UBなしで使用できます)。残念ながら、POD 以外の型に適用すると未定義の動作が発生するため、多くの C++ ではまだ役に立ちません。

于 2011-02-04T15:09:37.967 に答える
0

まず、マクロにセミコロンを入れるのは悪い考えです。セミコロンは大きな式では使用できません。

unsigned long第二に、ポインター用に特別に設計された完全に適切な型 (つまり、stdint.h で提供される size_t と ssize_t) がある場合に使用するのは悪い考えです。これらの型は、32 ビットおよび 64 ビット アーキテクチャを使用する場合に特に役立ちます。GCC には、正しいワード サイズを使用するために、printf の拡張機能「%zu」があります。

G++ はコンパイル時にこれを計算します。少なくとも -O2 と -O3 を POD 型で使用します。

于 2011-02-04T19:08:23.267 に答える