Rangeの勉強その6

翻訳の続き。これで最後。

6 Range adapters (Part4)
この提案の最後ではrange adapterを扱う. この小さなヘルパークラス達は次のような利点を持つ:

  • operator|()によって簡単にアダプターを組み合わせることが出来る.
  • ユーザーはiteratorとrangeの型の命名を完全に回避できる---すべては関数呼び出しのうちに推論される.

adapterはその本当の性質がまだ明らかでないが, iterator adapter上にすべて構築可能である. operator|()は単に, 通常make_XX()などと呼ばれる関数に対してのショートネームである. けれどもoperator|()の方が可読性に優れている---特に何度も適用されるような場合には.

Eric Nieblerのrange_exのcodeはこれらのadapterのいくつかを実装している.


6.1 Specification
以下のfwdRngは型がForwardRangeであるような式である, biRngは型がBidirectionalRangeであるような式であり, rndRngは型がRandomAccessRangeであるような式である. predは型がUnaryPredicateであるような式であり, biPredは型がBinaryPredicateであるような式である. funは型がUnaryFunctionであるような式である. そして、nとmは問題となるrangeのsize_typeと型が一致するような整数式である.


一般的な必要条件(General requirements):
1. range R(常に左辺の引数となる)とrange adapter RA(常に右辺の引数となる)に, operator|()を適用させる(Applying)ことによって, Rと等しいrangeのコンセプトに適合する, 新しいrangeが生成される.

2. それ以外の場合のoperator|()の戻り値の型は未規定(unspecified)である.

3. range adapterがstd名前空間内で実装されてるので, operator|()はADLによって探索される.

4. operator|()は, 遅延的に(lazily), 新しい挙動を追加するのに使われ, 決して左辺の引数を変更することは無い.
5. 左辺の引数から展開されるiteratorはすべて、無修飾のbegin()とend()の呼び出しによって展開される.
6. 以下のthrow節に加えて, operator|()はiteratorのコピーの結果, 例外を投げることが有るかもしれない.

有効な式:
1. fwdRng | std::filtered( pred )

  • 事前条件(Precondition): rangeのvalue-typeはpredの引数の型に適合可能である.
  • 事後条件(Postcondition): returnされるrange内のすべての要素xについて, pred(x)はtrueである.
  • 例外の送出(Throws): predのコピーコンストラクタが投げるものはどれでも.

1. fwdRng | std::adjacent_filtered( biPred )

  • 事前条件: rangeのvalue-typeはpredの引数の型に適合可能である.
  • 事後条件: returnされるrange内のすべての隣接する要素[x,y]について, pred(x)はtrueである.
  • 例外の送出(Throws): biPredのコピーコンストラクタが投げるものはどれでも.

2. fwdRng | std::transformed( fun )

  • 事前条件: rangeのvalue-typeはfunの引数の型に適合可能である.
  • 事後条件: returnされるrange内のすべての要素xについて, xは, もとのrangeの対応する要素yに対してのfun(y)の結果(result)である.
  • 例外の送出: funのコピーコンストラクタが投げるものはどれでも.

3. fwdRng | std::indirected

  • 事前条件: rangeのvalue-typeで単項演算子 operator*()が定義されている.
  • 事後条件: returnされるrange内のすべての要素xについて, xは, もとのrangeの対応する要素yに対しての*yの結果である.

4. biRng | std::reversed

  • Returns: もとのiteratorにreverse_iteratorがラップされたかのような振る舞いをするiteratorを持つ, rangeが返る.

5. fwdRng | std::map_values

  • 事前条件: rangeのvalue-typeはstd::pairのインスタンスである.
  • 事後条件: returnされるrangeのすべての要素xについて, xは, もとのrangeの対応する要素yに対してのy.secondの結果である.

6. fwdRng | std::map_keys

  • 事前条件: rangeのvalue-typeはstd::pairのインスタンスである.
  • 事後条件: returnされるrangeのすべての要素xについて, xは, もとのrangeの対応する要素yに対してのy.firstの結果である.

7. fwdRng | std::moved

  • Returns: もとのiteratorにmove_iteratorがラップされたかのような振る舞いをするiteratorを持つ, rangeが返る.

8. fwdRng | std::uniqued

  • 事前条件: rangeのvalue-typeはoperator==()で比較可能である.
  • 事後条件: returnされるrangeのすべての隣接する要素[x,y]について, x==yはfalseである.

9. fwdRng | std::sliced(n,m)

  • 事前条件: 0<=n && n <= m && m < size(fwdRng).
  • Returns: make_range(fwdRng, n ,m).

10. fwdRng | std::tokenized( regex )
fwdRng | std::tokenized( regex, i )
fwdRng | std::tokenized( regex, rndRng )
fwdRng | std::tokenized( regex, i, flags )
fwdRng | std::tokenized( regex, rndRng, flags )

  • 事前条件:
  • Tはtypename range_value< decltype(fwdRng) >::typeを表す. このときregexはbasic_regexまたはbasic_string型を持つか, これらのどちらかに暗黙的に変換可能である.
  • iはint型を持つ
  • rndRngのvalue-typeはintである.
  • flagsはregex_constants::syntax_option_type型を持つ.
  • Returns: もとのiteratorregex_token_iteratorがラップされたかのような振る舞いをするiteratorを持つrangeが返る. rangeに含まれる先頭のiteratorは, regex_token_iteratorのコンストラクタにtokenized()の引数を転送して構築される.
  • 例外の送出: 同等なregex_token_iteratorを構築, コピーするときに投げるものはどれでも.

6.2 議論

  • 我々はもっと多くのrange adapterを提供するべきだろうか? 誰か他に思いつく?
  • adjacent_transformedも候補に挙げられるべきだろうか?

7 謝辞
Howard Hinnant, Dietmar KuehlそしてWalter Brownらによる建設的で, 厳しくも率直なフィードバックに感謝する. この提案で提出されたrange adapterはEric Nieblerによって開発されたアイデアをもとにしている.

半月かかった。英語難しい。

今回も例によって不安な部分があります。
"adapterはその本当の性質がまだ明らかでないが"節の翻訳が怪しいと思う・・・