本の虫

著者:江添亮
ブログ: http://cpplover.blogspot.jp/
メール: boostcpp@gmail.com
Twitter: https://twitter.com/EzoeRyou
GitHub: https://github.com/EzoeRyou

アマゾンの江添のほしい物リストを著者に送るとブログ記事のネタになる

筆者にブログのネタになる品物を直接送りたい場合、住所をメールで質問してください。

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