10

レガシー APIのC++ラッパーを作成しています。この API は、余分なデータを保持するためのポインター値を提供します。これを使用してSmall Buffer Optimizationを実装したいと考えています。

特定のタイプがPODであり、次の範囲内に収まるかどうかをチェックするis_small_pod メタ関数を実装しました。void*

template< typename Type >
struct is_small_pod
  : std::integral_constant<
        bool
      , std::is_pod< Type >::type::value
        && sizeof( Type ) <= sizeof( void* )
    >
{};

そして、私は次のように値を設定しています:

// void*& param;
if( detail::is_small_pod< Type >() )
{
    *static_cast< Type* >( &param ) = value;
} else {
    param = new Type( value );
}

この最適化を正しく実装していますか? 値のアラインメントがポインターのアラインメントと互換性がない場合、これは失敗すると思います (奇妙なケースもあります)。その状況は可能ですか、それとも私が考えすぎているだけですか? メタ関数を拡張して、互換性のあるアラインメントもチェックするにはどうすればよいですか?

4

2 に答える 2

8

型のアラインメントをその型のサイズよりも大きくすることはできません。

3.11 アラインメント [basic.align]

[...]アラインメントは、特定のオブジェクトを割り当てることができる連続するアドレス間のバイト数を表す実装定義の整数値です。

5.3.3 sizeof [expr.sizeof]

2 - [...] n要素の配列のサイズは、要素のサイズのn倍です。

alignof(void *) < sizeof(void *)したがって、ほとんどのプラットフォームでは当てはまらない場合にのみ、コードが壊れることがあります。

安全のために、次のように書くことができます。

template< typename Type >
struct is_small_pod
  : std::integral_constant<
        bool
      , std::is_pod< Type >::type::value
        && sizeof( Type ) <= sizeof( void* )
        && alignof( Type ) <= alignof( void* )
    >
{};
于 2012-10-25T21:14:46.190 に答える
0

一般的なアプローチと同様に、いつでも自分の理論をテストしてみることができます。私はあなたがこのようなことをすると思います:

template< class Type >
bool TestAlignmentSanity( Type value )
{
    // This function is only valid for small POD types
    if( !detail::is_small_pod< Type >() )
        return false;

    // Temporary space covering alignments spanning the size of a void*
    const int nBytes = sizeof(void*);
    char buffer[sizeof(Type) + nBytes - 1];

    // For each target alignment, test that a copy is successful.
    for( int i = 0; i < nBytes; i++ )
    {
       Type * target = static_cast< Type* >( &buffer[i] );

       // Sanity-check that the pointer was actually aligned as we requested
       if( (char*)target != &buffer[i] ) return false;

       // Copy and test that the result is as expected.  Assumes '==' operator
       // is defined...  Otherwise, implement with byte comparisons.
       *target = value;
       if( !(*target == value) ) return false;
    }

    return true;
}

ここで、データ型が a のサイズにまたがる任意のアラインメントにコピーできることをテストしましたvoid*。それはただの考えです。=)

于 2012-10-25T21:17:58.033 に答える