2015-11-25

C++標準化委員会の文書のレビュー: P0080R0-P0089R0

P0080R0: Variant: Discriminated Union with Value Semantics

variantライブラリの提案。

P0081R0: A proposal to add sincos to the standard library

sinとcosを同時に計算してくれるsincosライブラリの提案。

ある値に対してsinとcosを同時に両方共計算したいことはよくある。同じ値を二度引数として別の関数に渡すのは間違いのもとである。また、x86などの一部のアーキテクチャには、sinとcosを同時に計算してくれる効率的な命令が用意されている。

GCCにあるsincosは、結果をポインターで受け取るが、ポインターが絡むとエイリアスなどの問題が出てくるので、提案されている文法は、単に値をpairで返す。

#include <utility>
namespace std {

pair<double, double> sincos(double x) noexcept;

// その他、floatなどのオーバーロード関数
}

std::tieを使えば、pairは意識せずにすむ。

#include <tuple>

void f( double x )
{
    double s, c ;

    std::tie( s, c ) = std::sincos( x ) ;
}

[PDF] P0082R0: For Loop Exit Strategies (Revision 1)

forループから、条件式がfalseになって抜けた時と、breakで抜けた時に実行されるブロック文を記述できるif for文の提案。

if for ( ... ; 条件 ; ... )
    {
        // for文のブロック文
    }
{
    // 条件がfalseになって抜けた時に実行される   
}
else
{
    // breakで抜けた時に実行される。
}

この論文筆者が主張するには、以下のようなコードより読みやすいらしい


for ( ; 条件 ; )
{
    // for文のブロック文
}

if ( !条件 )
{
    // 条件がfalseで抜けた
}
else
{
    // breakで抜けた
}

どうも必要性がわからない。そういう複雑なfor文は関数として切り分ける方が読みやすいし、lambda式のある現在、ライブラリベースの実装でも良い気がする。

[PDF] P0083R0: Splicing Maps and Sets (Revision 2)

std::listには、spliceという機能がある。これを使えば、あるlistコンテナーで管理されている要素を、所有権ごと別のコンテナーに移動することができる。


    std::list a { 1, 2, 3 } ;
    std::list b { 4, 5, 6 } ;

    a.splice( a.end() , b ) ;

    // a = { 1,2,3,4,5,6}
    // b = { }

たといint型のようにコピーやムーブの処理が軽くても、メモリの動的な確保と解放のコストは大きい。spliceは、所有権ごと要素を移すことで、不要なコストを削減できる。

しかしmapとsetには、このようなspliceがないし、簡単に提供できない。

そこで、連想コンテナーから要素の所有権を切り離せるextract、所有権が切り離された要素を管理するnode_ptr、node_ptrを受け取るinsertを追加する提案。

[PDF] P0084R0: Emplace Return Type

emplaceが構築したオブジェクトへのリファレンスを返すようにする提案。

emplaceは、コンテナーに挿入すべきオブジェクトを渡すのではなく、オブジェクト構築時の引数を渡す。しかし、構築後のオブジェクトを操作したい場合、コンテナーからそのオブジェクトをわざわざ引っ張り出してこないといけない。

struct X
{
    X( int, int, int ) ;

    void do_something() ;
} ;

int main()
{
    std::vector<X> v ;

    // 構築
    v.emplace_back( 1, 2, 3 ) ;

    // 構築後のオブジェクトを引っ張りだして操作
    v.back().do_something() ;
}

emplaceが構築後のオブジェクトへのリファレンスを戻り値として返すようにすれば、このコードは簡略化できる。

v.emplace_back( 1, 2, 3 ).do_something() ;

提案では、emplace_frontとemplace_backを変更するよう提案している。従来のfrontとbackは戻り値を返さないが、これはどうせオブジェクトを実引数で渡すので、コピー/ムーブされたオブジェクト

P0085R0: Oo... adding a coherent character sequence to begin octal-literals

新しい8進数リテラル0oを追加する提案。

0o11 ; // 10進数で9
0O11 ; // 9

既存のプレフィクス0から始まる8進数リテラルは、現代人には馴染みが薄く混乱のもとである。このリテラルは、まだコンピューターが原始的で、パーソナル・コンピューターといえば個人が8bit CPUや16bit CPUを使って自力で作っていた時代からの名残である。

この提案では、新しい8進数リテラルのプレフィクス0o(数字ゼロにアルファベットの大文字小文字のオー)を追加する。

新しい8進数リテラルの追加によって、8進数リテラルへの注目度を上げ、この新しい8進数リテラルを解説する時は、古い8進数リテラルへの注意も併記して問題認識を高め、いずれ既存の8進数リテラルをdeprecated扱いにして、除去することを目指している。

プレフィクス0oの8進数リテラルは、すでに、haskell, OCaml, Python 3.0, Ruby, Tcl Version 9でサポートされていて、ECMAScript 6もサポートする予定であるという。

[PDF] P0086R0: Variant design review

[PDF] P0087R0: Variant: a type-safe union without undefined behavior (v2)

[PDf] 0088R0: Variant: a type-safe union that is rarely invalid (v5)

ライブラリベースの型安全unionを実現するvariantライブラリの設計事情と、議論が別れている設計の差異について。

variantはinvalid/emptyな状態を許容すべきかどうか。その状態をクエリー可能にすべきかどうか。

純粋な数学的観点からinvalid/emptyなvariantは認めるべきではないという意見と、その場合、ユーザーが自前でダブルバッファリングをしなければならないので結局使いづらい。variantがダブルバッファリングを提供すべきだ。例外を投げないムーブのある型の場合、メタプログラミングでvariantのダブルバッファリングは除去できるし、将来的にはTransactional Memoryであらゆる型のダブルバッファリングが除去できるなどと豪語する壮大なお花畑意見まである。

[PDF] 0089R0: Quantifying Memory-Allocatiom Strategies

メモリ確保にローカルアロケーターを使うことによるパフォーマンス向上のベンチマークと考察

ローカルアロケーターを使い、個々のオブジェクトのデストラクターを呼ばずに、一括して解放することによる、パフォーマンスの向上の余地は十分にあると主張している。

ドワンゴ広告

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

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

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

2 comments:

Anonymous said...

バリアントについては、未初期化の状態だけ空を許せばいいかと思います。
まぁ、Enum設定するときも無を表す状態を作る派です。
ユーザーがあえて空にする欲求ってありますかねー。
危ないオブジェクトだけのバリアントでも構築したときでしょうか。
それならユーザー側が安全な型を設定すればいい話で、
システムが空を要求するのは、初期化時以外でありますでしょうか。
型数に制限はなかったはずです。
sincosは円回転するときによく使うのでまぁありがたいかな。
std::tieをよく理解してないのでまた目からうろこが落ちました。
ifforはフラグ制御するよりは直観的ですが、そんなに困ってないですね。
8進リテラルの正しい使い方ってなんかあるんでしょうか。確かに桁そろえで先頭に数字の0をつけたい欲求がたまに沸いてきてバグを引き起こすのですが、まぁ整理してほしかった事案なので整理されてください。

Anonymous said...

ECMAScript 6 (ECMAScript 2015)はすでにリリースされているのでもう予定ではなく確定です。