2016-08-02

C++標準化委員会の文書: P0330R0-P0339R0

[PDF] P0330R0: User-Defined Literals for size_t

std::size_t型を返すuser defined literal suffixのzuを追加する提案。これにより、size_t型の変数をautoで宣言できるようになる。

using namespace std::support_literals;
auto size = 123zu ;

サフィックスのない整数リテラルの型はint型になるため、これまでズボラなプログラマーは符号付き整数をstd::size_t型の変数に代入したり比較したりしていた。符号付き整数と符号なし整数を変換したり比較すると、思いがけぬ挙動につながるので、好ましくない。

P0331R0: P0331r0 : Motivation and Examples for Multidimensional Array

多次元配列array_refの動機と利用例

P0332R0: P0332r0 : Relaxed Incomplete Multidimensional Array Type Declaration

array_refは、配列型を渡すことによって、一部を動的なサイズにすることができる。

array_ref< int [][5][] > a ;

これを実現するために、配列の宣言の文法を変更する。

P0333R0: P0333r0 : Improving Parallel Algorithm Exception Handling

Parallelism TSで並列ベクトル実行ポリシーでアルゴリズムを実行した時に、要素アクセス関数が例外を投げた場合、直ちにstd::terminateが呼ばれる。これは他の実行ポリシーのexception_listを投げる挙動と違い、一貫性がない。そこで、並列ベクトルポリシーの場合でもexception_listを投げるようにする。また、並列ベクトル実行ポリシーはbad_allocも投げることがある。

P0334R0: P0334r0 : Immutable Persistent Containers

変更できないコンテナー、immutable_listの提案。

immutable_listは要素を変更出来ないコンテナーだ。「変更」したいときは、新しいimmutable_listのオブジェクトを作る。要素は参照カウンターで管理されている。

確かに、標準ライブラリにほしいコンテナーだ。Haskellが参考にされている。

[PDF] P0335R0: Context Tokens for Parallel Algorithms

並列アルゴリズムにコンテキストトークンを追加する。

parallel::for_each( vec, 0, N, []( auto i )
    {
        parallel::for_each( par, 0, N, func ) ;
    } ) ;

このように、並列アルゴリズムがネストする場合で、外側の実行ポリシーがベクトルで、内側の実行ポリシーが並列の場合、挙動は未定義になる。この誤りを検出する方法がない。

そこで、要素アクセス関数(この場合、lambda式やfunc)にコンテキストトークンを与え、同トークン経由で並列アルゴリズムを呼び出す方法を付け加える。

parallel::for_each( vec, 0, N, []( auto context, auto i )
    {
        context.for_each( par, 0, N, func ) ;
    } ) ;

これにより、実行ポリシーの伝播が正しく行われるようになる。

[PDF] P0336R1:Better Names for Parallel Execution Policies in C++17

並列アルゴリズムの実行ポリシーの名前をリファクタリングする提案。シングルトンオブジェクトのseq, par, vecは変わらないが、std::execution名前空間の下におかれるようになる。

P0337R0: P0337r0 | Delete operator= for polymorphic_allocator

polymorphic_allocatorからoperator =を削除する提案。

polymorphic_allocatorはステイトフルなアロケーターである。propagate_on_container_copy_assignment と propagate_on_container_move_assignmentはfalseを返す。これは意図的なものである。理由は。ステイトフルなアロケーターは一度コンテナーに入れたら、そこから動かすべきではないからだ。その設計思想から考えれば、そもそもoperator =を提供すべきではない。operator =を使って失敗する例がいくつもある。そこで、operator =を削除する。

[PDF] P0338R0: C++ generic factories

汎用的なfactory関数の提案。

C++には、いわゆるmake系のfactory関数が存在する。例えば、make_sharedとかmake_uniqueとかmake_pairなどだ。

make関数が作られる理由は主に2つある。

新しく型を作るfactory関数

back_inserter、make_optional、make_ready_future, make_expectedなど、新たに型を作り、そのオブジェクトを返すものがある。

emplace構築を行うもの

make_uniqueやmake_sharedなど。

また、make_pairやmake_tupleのような、新たに型を作り、かつemplace構築まで行うものがある。

この提案は、そのような様々なmake_foobar関数を、make関数に統一しようと言う提案だ。例えば以下のようなードが、

int v=0;
auto x1 = make_shared<int>(v);
auto x2 = make_unique<int>(v);
auto x3 = make_optional(v);
auto x4v = make_ready_future();
auto x4 = make_ready_future(v);
auto x5v = make_ready_future().share();
auto x5 = make_ready_future(v).share();
auto x6v = make_expected();
auto x6 = make_expected(v);
auto x7 = make_pair(v, v);
auto x8 = make_tuple(v, v, 1u);
future<int&> x4r = make_ready_future(std::ref(v));
auto x1 = make_shared<A>(v, v);
auto x2 = make_unique<A>(v, v);
auto x3 = make_optional<A>(v,v);
auto x4 = make_ready_future<A>(v,v);
auto x5 = make>(v, v);
auto x6 = make_expected<A>(v, v);

以下のように書ける。

int v=0;
auto x1 = make<shared_ptr>(v);
auto x2 = make<unique_ptr>(v);
auto x3 = make<optional>(v);
auto x4v = make<future>();
auto x4 = make<future>(v);
auto x5v = make<shared_future>();
auto x5 = make<shared_future>(v);
auto x6v = make<expected>();
auto x6 = make<expected>(v);
auto x7 = make<pair>(v, v);
auto x8 = make<tuple>(v, v, 1u);
future<int&> x4r = make<future>(std::ref(v));
auto x1 = make<shared_ptr<A>>(v, v);
auto x2 = make<unique_ptr<A>>(v, v);
auto x3 = make<optional<A>>(v,v);
auto x4 = make<future<A>>(v,v);
auto x5 = make<shared_future<A>>(v, v);
auto x6 = make<expected<A>>(v, v);

make関数にテンプレート名を渡すと、それぞれに対応したfactory関数として振る舞う。

テンプレート名ではなく、型を渡すことも可能である。これによって具体的に指定することも可能になる。

auto x = std::make< unique_ptr<long>>(0) ;

P0091によって、コンストラクターからテンプレート実引数の推定ができるようになるので、make関数の一部の機能は普通に書けるようになるが、それでもmake関数の優位な点はいろいろあると主張している。

customization pointとしては、std::factory_traits<T>が提供されている。これを特殊化することによってユーザー定義のクラスに対する挙動を追加できる。

[PDF] P0339R0: polymorphic_allocator<void> as a vocabulary type

polymorphic_allocator<void>を、型を指定せずに使えるあロケーターにしようと言う提案。

ドワンゴ広告

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

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

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

1 comment:

Anonymous said...

makeの統一はいい案だと思います。が、もっと名前的に的確な名前って無いでしょうか。makeでもなれればいいですけど、なんか妙な違和感が。。。