2009-11-12

C++0x: Post Santa Cruz mailingの簡易レビュー

ISO/IEC JTC1/SC22/WG21 - The C++ Standards Committee

Post Santa Cruz mailingが公開された。今回は、面白そうなペーパーが多い。最新のドラフトは、N3000である。

n2979: Moving Swap Forward (revision 1)

decltype、戻り値の型の後置記法、関数テンプレートへのデフォルト引数の追加により、我々には、強力なSFINAEがもたらされた。このSFINAEのテクニックをサポートするため、誰もが必要とするであろうヘルパー関数を定義しようというもの。以下のようなコードだ。

template<class T>
 T&& value(); // not used

これは、decltypeの中で用いられることを想定している。

template<class To, class From>
 decltype(static_cast<To>(value<From>())) convert(From&&);

もし、このvalue()を使わない場合、上記のコードは、以下のようになる。

template<class To, class From>
  decltype(
    static_cast<To>(
      static_cast<From &&> (
        *reinterpret_cast<From *>(null_ptr)
      )
    )
  ) convert(From&&);

これは甚だ面倒であるし、また読みにくいので、当然、我々はvalue()関数と同等のものを、自前で書く事になるだろう。それほど一般的なテクニックなら、標準にいれてしまおうというものである。

このvalue()は、実行時に用いることを想定していない。どうやって、間違った使い方をコンパイル時にエラーにして、未然に防ぐかということも、提案されている。

また、swap(), forward(), move()といった関数と、このvalue()だけを定義した、別のヘッダを付け加えようとも提案している。なぜならば、この四つの関数は、言語側に近いのだが、これを使うために、<type_traits>を必要とするのは、やや大げさすぎるからだ。

N2980: SCARY Iterator Assignment and Initialization Revision 1

これは、コンテナのイテレータの実装に起因する問題で、コンテナのアロケータの型が違う場合、イテレータの実装方法によっては、要素の型さえ同じなら、同じように扱われてしまうという問題を取り扱っている。今まで、標準規格では、これを実装依存としてきたが、これを認めるように規定するものである。not dependantな実装のライブラリは、修正を迫られるだろう。

template < typename T >
class _List_Iterator {} ;

template < tyepname T, class Allocator = allocator >
class list{
    typedef _ListIterator iterator ;
}

この実装を、independantな実装という。逆に、コンテナにネストして、直接iteratorを実装しているようなコードを、not independantな実装という。このようなindependant実装をしている場合、イテレータは、コンテナのアロケータの型に依存しないので、アロケータの型だけ違うイテレータ同士の処理を、コンパイルエラーにできないというものである。

set<int, C1, A1>::iterator i1;
set<int, C2, A1>::iterator i2 = i1; // different comparator
set<int, C1, A2>::iterator i3 = i1; // different allocator

ここで、i3を、怖い初期化(SCARY initialization)という。アロケータの実装次第で、動くかどうかが変わるからだ。この提案では、この怖い初期化を、合法にしようというものである。そのためには、independantな実装が必須となる。

この初期化は、確かに「怖い」が、必ずしも「危険」とは限らない。それに、もしこの初期化がコンパイルエラーになったとしても、防げるバグはほんの一部である。この問題を未然に防ぎたければ、rangeなどのテクニックの方が、よほど役に立つ。そういうわけで、この怖い初期化を、規格で合法にする。

N2981: Proposal to Simplify pair (rev 3)

pairは、本来シンプルな型だったはずだ。ところが、やれmapのサポートだの、move semanticsだの、emplaceだの、scoped allocatorだの、様々な言語仕様の対応に追われて、恐ろしくふくれあがっている。いまや、pairクラスは、14個ものコンストラクタを持っている(暗黙に生成されるコンストラクタを除く)! これはどう考えても、ピザデブにも程がある。少し減らそうぜ、という提案。

N2982: Allocators post Removal of C++ Concepts (Rev 1)

コンセプト廃止に伴うアロケータの変更。また、アロケータがかなりのデブになってきているので、少し減量させようという提案もはいっている。

N2983: Allowing Move Constructors to Throw

N2855で、我々はmoveコンストラクタからのthrowを禁止した。だがちょっと待って欲しい。禁止したから何だというのだ。すでにthrowを禁止している部分は多く、いまさらmoveコンストラクタを禁止したからって、一体何になるというのだ。だいたい、throwが禁止されている状態で、テンプレートクラスでmoveコンストラクタを書こうとしたら、エキスパートレベルのテンプレートメタプログラミングのスキルが必要になってしまうではないか。throwぐらい認めてやろうではないか。

ただし、どうしてもthrowして欲しくない場合がある。それは我々も理解する所だ。従って、絶対throwしない場合のみ、moveをする、std::move_if_noexcept(x)を追加してやろう。また、最適化を容易にするために、新たなexception-specificationを追加してやろう。

なんか机上の空論っぽい提案なのだが、大丈夫なのだろうか。

N2984: Additional Type Traits for C++0x (Revision 1)

前回からの変更点。

  • Added is_constructible
  • Added is_nothrow_constructible
  • Made is_convertible a synonym for a two argument is_constructible
  • Renamed enum_base as underlying_type
  • Added Acknowledgements

以上。

N2985: C and C++ Thread Compatibility

名前の通り。提案ではなく、意見。

N2986: Equality Comparison for Unordered Containers

unorderd系のコンテナが、等しいかどうかを比較することについて論じている。つまり、operator ==()を実装するかどうかという話だ。このペーパーでは、ある種の問題では、二つのコンテナが等しいかどうかという情報は有益であることを述べている。さらに、等しいということを、どうやって定義するかという問題についても論じている。この提案では、二つのコンテナのsize()が等しく、要素の順序を問わず、すべての要素が、互いに等しければ、コンテナは等しいとしている。

unorderdコンテナ同士の比較は、どのように実装しても、かなり遅くなると思われる。もちろん、size()が異なるならば別だが。

N2987: Defining Move Special Member Functions

copyableとmovableなメンバが同居するクラスの、デフォルトのコピーコンストラクタ、moveコンストラクタの生成をどうするかというお話。

N2988: LWG Issue 897 and other small changes to forward_list

forward_listのerase_afterは、戻り値を返しても意味がないので、voidにしよう。また、規格にtypoがあるので、その修正。

N2989: Unified Function Syntax

まだまだ規格入りしない。頼むぞ、お前には期待しているのだ。私を失望させるな。

N2990: Core issue 789: Fixing Raw Strings wrt. Trigraphs

トライグラフを廃止したいが、IBMが自社コードに互換性の問題があると報告してきた。トライグラフを廃止しつつも、IBMに配慮するような提案。

N2991: Core issue 743: decltype(...) name qualifiers

decltypeにnested-name-specifierが使えない問題の修正。今回の改訂は、文面の変更だけ。

N2992: More Collected Issues with Atomics

Atomicに関する、文面上の細かい修正。

N2994: constexpr in the library: take 2

constexprに関する諸問題を取り扱っている。constexprが、引数に値しか認めないことを、テンプレートコードとの絡みで問題になるとしている。ただし、conceptexpr自身の問題は、単に紹介だけにとどめている。このペーパーでは、ある種の標準ライブラリでは、constexprなコンストラクタが有益であり、当然提供するべきであると提案している。

N2996: A Simple Asynchronous Call

改訂版。意見を取り入れて、少し規格が変わっている。単なる文面程度の変更ではなく、注意すべき変更点がある。

N2997: Issues on Futures (Rev. 1)

これは、N2996とは、別々のペーパーになっているが、N2996の改訂をするにあたっての、補助的な提案である。N2996では、is_ready()が廃止されているが、is_ready()を規格から取り除くように出来るように、その他の部分の整合性をとる変更である。

N2998: Reaching Scope of Lambda Expressions

N2977で、lambdaの参照できる範囲を、 immediately-enclosing function or lambda expressionに制限したのだが、これはきつすぎる制限で、現実のコードが悲惨なことになってしまう。

そこで、immediately-enclosing function or lambda expressionから、innermost enclosing function and its parametersに変更されるようだ。これで、冗長なコードを書かずにすむ。おかしいとは思っていたのだ。

N3010: Rvalue References as "Funny" Lvalues

rvalue referenceの戻り値を、lvalueとして扱いたいが、少々問題がある。そこで、"Rref lvalue"というファニーなlvalueを付け加えようというお話。

Post Santa Cruz mailingではないが、参考の為に簡易レビュー。

N2951: forward

forward()は、最終的には、単にstatic_cast<T&&>(u)を返すに過ぎぬのだが、スマートな実装をすべきかという議論。六つの実装例と、六つのテストケースを示して、この問題について論じている。N3000には、採用されたらしい。

No comments: