5

a組み込み配列または適切な を持つクラス型のオブジェクトがoperator []あり、その返された型自体にインデックスを付けることができる場合、分離するのではなく可変引数呼び出しでそれらすべてにインデックスを付けることができる汎用関数をどのように作成すればよいですか?ブラケットブロック? つまり、次のような式を作成できます。

a[i0][i1]...[iK]

そして、それを単一の関数として記述できるようにしたい:

slice( a, i0, i1, ..., iK )

C++ の規則はoperator []単一の引数で動作する必要があるため、可変個引数との互換性が低くなります。(この質問は、似たようなことを尋ねようとした Usenet スレッドに基づいています。最終的には、ネストされている可能性のある組み込み配列のみを自分で解決しました。)

最初の刺し傷:

template < typename T, typename U >
constexpr
auto slice( T &&t, U &&u ) noexcept(???) -> ???
{ return ce_forward<T>(t)[ ce_forward<U>(u) ]; }

template < typename T, typename U, typename V, typename ...W >
constexpr
auto slice( T &&t, U &&u, V &&v, W... &&w ) noexcept(???) -> ???
{
    return slice( ce_forward<T>(t)[ce_forward<U>(u)], ce_forward<V>(v),
     ce_forward<W>(w)... );
}

ce_forward関数テンプレートは-マークがconstexpr付いていstd::forwardます。(標準でマークできるものの中には、constexprそうでないものもあります。) 戻り値の型と例外仕様のスポットに入れる適切なものを見つけようとしています。私が知っているいくつかのケースと警告は次のとおりです。

  • 組み込みでoperator []は、1 つのオペランドがデータ ポインター (または減衰配列参照) であり、もう 1 つのオペランドが列挙型または整数型である必要があります。オペランドはどちらの順序でもかまいません。適切な型への明確な (非明示的な?) 変換を使用して、オペランドをクラス型に置き換えることができるかどうかはわかりません。
  • クラス型はoperator []、非静的メンバー関数として定義できます。このような関数は、( 以外にthis) 1 つのパラメーターのみを持つことができます。
  • 組み込み演算子はスローできません。(オペランドが UDT 変換に基づいている可能性がある場合を除きます。この変換が唯一の可能なスロー ポイントです。) 境界エラーによって引き起こされる未定義の動作は、ここでは私たちの範囲を超えています。
  • 最後のインデックス呼び出しが左辺値参照、右辺値参照、または値を返すかどうかは、 の戻り値の型に反映される必要がありsliceます。
  • (最終?) 呼び出しが値によるものである場合はstd::is_nothrow_move_constructible<ReturnType>::value、例外指定に対して OR を使用する必要があります。(参照による返品はnoexcept.)
  • 組み込み演算子に配列が含まれる場合、そのステップで返される参照は、配列も r-value 参照である必要があります。(配列とは異なり、ポインターはターゲットの左辺値と右辺値の状態を失うため、これは一種の欠陥です。そのため、従来の戻り値は常に左辺値参照になります。)
  • クラス型インデックス演算子の場合、例外仕様セクションと戻り型セクションが、関数本体が使用する同じオーバーロード (複数ある場合) を参照していることを確認してください。this( const/ volatile/both/neither および/または&/ /neither)の修飾のみが異なるオーバーロードには注意してください&&
4

2 に答える 2

1

関数の正しい戻り値を取得するにsliceは、正しい結果の型を計算するヘルパー テンプレートを作成できます。例えば:

template <typename T, typename U, typename... V>
struct SliceResult {
    typedef typename SliceResult<T, V...>::Type Type;
};

template <typename T, typename U>
struct SliceResult<T, U> {
    typedef typename std::underlying_type<T[U(0)]>::type Type;
};

slice関数は を返しますSliceResult<...>::Type

于 2012-06-04T07:59:09.367 に答える