3

式 SFINAEは、同じことを行ういくつかの代替関数を記述し、コンパイルするのに最適な関数を選択するための非常に便利な方法です。関数プロトタイプで重要な式に言及し、それらが無効な場合、プロトタイプは無視され、別の式が選択されることを願っています。

これは、式が未定義の場合のプロトタイプを宣言することを除いて、非常に便利です。通常、プロトタイプのセットは、相互に排他的なドメインに分割する必要があります。これは、オーバーロードの解決という観点では等しい可能性があり、2 つをオーバーロード セットに入れるとあいまいさが生じるためです。

で使用するために、特定の式の昔ながらの特性タイプをいつでも定義できますstd::enable_if

template< typename s, typename t, typename u, typename = void >
struct is_product_serializable : std::false_type {};

template< typename s, typename t, typename u >
struct is_product_serializable< s, t, u, typename std::conditional< true, void,
   decltype( std::declval< s >() << std::declval< t >() * std::declval< u >() )
>::type >
    : std::true_type {};

から何かを派生させる必要がなければ、は関数プロトタイプに直接入ることができ、このボイラープレートはすべてなくなりますfalse_typestd::conditional

代替手段はありますか?おそらく、型推論を妨げない関数のオーバーロードのランクを下げる方法はありますか?

4

1 に答える 1

0

1 つの代替手段は、タグのようなダミー パラメータを追加するディスパッチャー関数を追加して、引数リストを異なるものにする余裕を持たせることです。

// "Primary" template is just a dispatcher
template< typename ... args >
void chuck( args && ... rem ) {
    return chuck_impl( 0, std::forward< args >( a ) ... );
}

// preferred alternative matches int to 0 but is controlled by SFINAE
template< typename t, typename u, typename ... args >
auto chuck_impl( int, t && a, u && b, args && ... rem )
-> typename std::conditional< true, void, decltype( blah( a, rem ... ) * b ) >::type {
    blah( a, rem ... ) * b;
}

// fallback requires int => float conversion
template< typename t, typename u, typename ... args >
void chuck_impl( float, t && a, u && b, args && ... rem ) {
    bleh( a + chuck_impl( b, rem ... ) );
}
于 2013-02-20T06:10:32.810 に答える