2016-06-16

C++標準化委員会の文書: P0210R0-P0219R0

P0210R0: A light-weight, compact dynamic array

軽量な動的配列ライブラリの提案。

vectorはamortized constant timeを実現するために、実際に必要なサイズよりも大きなサイズのメモリを確保している。これはメモリ消費量を必要以上に上げる。

そのため、そのような挙動を行わない軽量な動的配列ライブラリの追加をする提案。

このライブラリは、insert, push_back, emplace{,_back}, eraseといったメンバー関数は提供しない。これらのメンバー関数は、汎用的なコンテナーの要件には定められておらず、特定のコンテナーがそのような操作を効率的に実装できる場合にのみ提供されるものだからだ。

reserveやcapacityもない。

resize(n)は要素数をnにする再確保を常に行う(ただしn == size()の場合を除く)

このライブラリの名前をどうするかは自転車小屋の議論が続いている。

このライブラリはスタックからメモリを確保するdynarrayとは別の目的なので、別のライブラリとなる。

用途は、new T[n]の置き換えだ。

new T[n]にくらべて何が優れているのか。

  • サイズも一緒に管理される
  • クラスによってメモリが所有されるので、オブジェクトの破棄時にメモリも解放される
  • 要素に対して個々に破棄することができる

P0211R0: Allocator-aware library wrappers for dynamic allocation

アロケーターを使ってnew/make_unique/make_shared相当のことができるライブラリ。

new/make_unique/make_sharedは、operator newから生のストレージを確保して、オブジェクトを構築する。アロケーターでやるには、placement newでオブジェクトの構築を自前でやらなければならない。

auto p = new T( args ... ) ;
delete p ;

相当のことを、メモリ確保をアロケーターに変えて行いたい。このライブラリを使えば、以下のように書くことができる。

auto p = std::allocate_new<T>( alloc, args ... ) ;
std::allocate_delete( alloc, p ) ;

同様に、make_uniqueやmake_sharedも、以下のように書ける。

auto p = std::allocate_unique<T>( args ... ) ;
auto p = std::allocate_shared<T>( args ... ) ;

便利なライブラリだ。

P0212R0: Wording for [[maybe_unused]] attribute.

名前が使われないことをヒントとして示す[[maybe_unused]]の文面案。以前は[[unused]]だったが、改名された。

たとえば、以下の例でassertはプリプロセッサーマクロで、リリースビルドで消えてしまうので、コンパイラーからはresultが使用されていないように見え、変数が使われていないという警告を出すかもしれない。これをmaybe_unusedで解消できる。

int f(int x, int y)
{
    [[maybe_unused]] int result = error_check( x, y ) ;

    assert( result ) ;

    return do_something( x, y ) ;
}

P0213R0: Reexamining the Performance of Memory-Allocation Strategies

Fundamentals TSで追加される新しいメモリアロケーターのベンチマークテスト。

monotonicとは、メモリ解放をしないアロケーター。アロケーターオブジェクトの破棄時に、一括してメモリを解放する。メモリの中にリスト構造か何かをつくって開いている領域を探してといったメモリ管理が不要になるシンプルなデザイン

multipoolとは、確保する小さなサイズごとにテーブルを作りそこから確保する戦略のアロケーター

P0214R0: Data-Parallel Vector Types & Operations

1

ベクトル型を利用したSIMDプログラミングの説明

これ事態は提案ではなく、このような機能をC++に入れるにあたって委2員に基礎的な知識を説明するための文書とみえるが、それでも結構詳しく定義されている。

P0215R0: A Civil-Time Library

時間を、absolute time/civil time/time zoneに分類した上で、civil timeをサポートするライブラリの提案。

absolute timeとは、起点時間からのカウント数で、例えばtime_tなどが相当する。C++ではすでにchronoライブラリがある。

civil timeとは、グレゴリオ暦による年月日時分秒のことだ。これをサポートするライブラリを提案している。

タイムゾーンやサマータイムは含まれない。うるう秒も予測不可能なので含まれない。オブジェクトは時間は常に妥当な日付を指す。妥当でない日付を指定すると、正規化が行われる。例えば、1月32日を指定すると、2月1日になる。これにより、呼び出し側は範囲チェックを行わずに単純に日付同士の演算ができる。秒以下の時間は管理しない。

月同士の演算をする場合には、日を1日に合わせなければならない。

P0126R0:A Time-Zone Library

タイムゾーンライブラリの提案。

P0217R0: Wording for structured bindings

P0217R1: Wording for structured bindings

P0217R2: Wording for structured bindings

構造化束縛(structured bindings)の文面案。

多値を受け取る文法の提案。

publicな直接の非staticデータメンバーを持つクラス、配列、std::tuple, std::pairから、それぞれの要素の型と値で変数を初期化できる文法となっている。

int a[3] = { 1, 2, 3 } ;
// int, int, int
auto [ a1, a2, a3 ] = a ;

struct B { int x, double y, std::string z} ;
B b = { 1, 2.0, "3"} ;
// int, double, std::string
auto [ b1, b2, b3 ] = b ;

std::tuple< int, int, int > c{ 1, 2, 3 } ;
// int, int, int
auto [ c1, c2, c3 ] = c ;

これにより、多値を返す関数を使うのが楽になる。

std::tuple< int, double, std::string > f()
{
    return { 1, 2.0, "3" } ;
}

int g()
{
    auto [ x, y, z] = f() ;
}

文法は以下の通り。

auto [ identifier-list ] brace-or-equal-initializer

identifier-listのそれぞれの変数名は、リファレンス型になる。初期化子の要素数と同じだけの識別子がなければならない。

int a[3] = { 1, 2, 3 } ;
// ill-formed.
auto [ a1, a2 ] = a ;

変数は必ずリファレンス型になる。これについては注意が必要だ。構造化束縛にリファレンス修飾子がない場合、初期化子がコピーされて、変数名はそのコピーへのリファレンスになる。リファレンス就職しがある場合、コピーされず、初期化子へのリファレンスになる。

例えば、以下のコードは

int a[3] = { 1, 2, 3 } ;
auto [a1, a2, a3 ] = a ;

以下のコードと同じ意味になる。

int a[3] = { 1, 2, 3 } ;
auto _a[3] = { a[0], a[1], a[2] } ;

auto & a1 = _a[0] ;
auto & a2 = _a[1] ;
auto & a3 = _a[2] ;

初期化子のコピーが作られ、変数はそのコピーへのリファレンスとなる。

以下のように書いた場合は、

int a[3] = { 1, 2, 3 } ;
auto & [a1, a2, a3 ] = a ;

以下のようになる。

int a[3] = { 1, 2, 3 } ;

auto & a1 = a[0] ;
auto & a2 = a[1] ;
auto & a3 = a[2] ;

初期化子はコピーされず、変数は初期化子のオブジェクトへのリファレンスとなる。

P0218R1: C++17 Filesystem

filesystemライブラリ。

P0219R0: Relative Paths

Filesystemライブラリに相対パスを計算する機能を追加する提案。

基本的には、。あるパスに対して、別のパスからの相対パスを計算する方法で、例えば/a/b/cに対して/a/bからの相対パスを計算するとcになる。

これだけならば、現行のFilesystemにも存在するのだが、Symlinkを追ってほしい、追わないでほしい。冗長な.や..を除去してほしい。ほしくないと言った衝突するユーザーの要望があり、かつどのように振る舞うか意見が別れるコーナーケースも多数あるため、Boostでは10年にわたって紛糾している問題。これに対する解決案。

ドワンゴ広告

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

1 comment:

Anonymous said...

久しぶりに来ましたね!
動的なヒープライブラリって何に使うんでしょ。スタックで使うかstd::arrayでコンパイルタイムでやるか。など各種すでにあるので新規に作る必要性はそんなに感じません。vectorより軽い用途ということなのでしょうか。
いわゆるdate_tを標準でサポートする意義はそれなりにあると思うので入ってほしいです。それとそれのタイムゾーン変換も含めて。
構造化束縛っていうんですね。これ参照で受け取るというのはいろんな意味で扱いやすくなると思います。自分は参照を多用するのでこういう展開法は割と歓迎です。
ファイルシステムライブラリはどの程度システムへの依存を削れるのか興味あります。どこまで汎用化できるのか手腕に期待です。

unfied call syntax を誰か死守してほしいです。(汗
ブラックマジックが私の中で渦巻いている!!