2016-09-02

C++標準化委員会の文書: P0370R1-P0379R0

P0370R1: Ranges TS Design Updates Omnibus

Range TSに存在する問題を修正する提案。

P0371R1: P0371R1: Temporarily discourage memory_order_consume

タイトル通り、memory_order_consumeの利用を一時的に非推奨にする提案。

Linus Torvaldsも激怒していたように、現行のmemory_order_consumeには問題が山ほどあり、大抵の実装はその実装困難性からmemory_order_aquireと同じにしているのみならず、至るところでkill_dependencyや[[carries_dependency]]を明示的に使わなければならないので、不便なことこの上ない。

そこで、memory_order_consumeは改良が必要だが、それには時間がかかるので、それまでの間非推奨扱いにする。

P0372R0: P0372R0 - A type for utf-8 data

UTF-8の1単位を表現するchar8_t型の提案。

char8_tからcharへの標準変換はできるが、逆はできない。

C++11のときにchar8_tが必要だと訴えたら、charは古典的にバイト列を表現する型なので十分だ。char型以外の型があるのは混乱する。などと理解のないUnicodeの世界に生きていない名だたる委員達から散々に批判された。その委員達も、今では、「やっぱりchar8_tがないのは失敗だったなぁ」とぼやいている。それ見たことか。

[PDF] P0373R0: Proposal of File Literals

ファイルリテラルの提案。ファイルパスを指定すると、コンパイル時にそのファイルの内容が値として得られるリテラル。

例えば、hello.txtの中身が、

Hello,World

であるとすると

int main()
{
    // "Hello,World"と出力
    std::cout << tF"hello.txt" ;
}

プログラム中にデータを埋め込む需要がある。データを埋め込む方法は、C++の文法に従う方法や、実装依存の方法まで、様々ある。データはデータとしてファイルで独立させたい場合、実装依存の移植性のない方法を使わなければならない。

ファイルリテラルは、ファイルパスで指定されたファイルのデータを、コンパイル時に値として返す。その文法は

F"file pah"

を基本としてFの前にfile-encoding-prefixがつく。file-encoding-prefixは、b, t,L, u8, u, Uのいずれかだ。

bは、ファイルをバイナリデータとして扱う。ファイルリテラルの値は、ファイルをバイナリモードで開いて読み取ったものと同じ値で、その型はunsigned charの配列となる。null終端はされない。

例えば、hello.txtの中身が、UTF-8でエンコードされた

hello

であり、改行はないものとする。

auto data = bF"hello.txt" ;

この例では、dataの型はunsigned char [5]であり、その値は、{u8'h',u8'e',u8'l',u8'l',u8'o'}となる。null終端はされない。

tは、通常の文字列エンコードで、L,u8,u,Uはそれぞれの文字列のエンコードだ。この場合、コンパイル時にファイルの中身が対応する文字列のエンコードであると仮定され、生文字列リテラルに書かれたものと同じ扱いになる。

auto text = u8F"hello.txt" ;

これは、以下のコードと同じ意味だ。


auto text = u8R"(hello)" ;

ユーザー定義リテラルは、現状では問題があるので、将来の拡張案として保留するそうだ。

なるほど、需要はあると思う。

[PDF] P0374R0: Stream parallelism patterns

ストリーム並列パターンをサポートするための提案。Parallerism TSで、ある程度有名な並列アルゴリズムはあるが、ストリーム並列パターンへの対応が欠けているという。

P0375R0:[[exhaustive]] attribute for enums

enum名に対する[[eustive]属性の提案

以下のようなenumがあるとして、

enum color 
{
    red, green, blue  
} ;

コンパイラーは、以下のようなコードに警告を発することがある。

switch ( color c = get_color() ; c )
{
    case red :
        break ;
    case green :
        break ;
    case blue :
        break ;
}

なぜか。unscoped enumはenumerators以外の値になることもなるからだ。

そこで、この提案はコンパイラーの警告を抑制するための属性、[[exhaustive]]を提案している。

enum [[exhaustive]] color 
{
    red, green, blue  
} ;

これで、enumeratorsのみが使われることを明示的に指定するので警告を抑制できる。

素直にscoped enumを使えばいいと思うのだが。

P0376R0: A Single Generalization of std::invoke, std::apply, and std::visit

std::invoke, std::apply, std::visitを一般化したtupleの展開までできるstd::callの提案。

便利だが使うのが面倒な気がする。汎用性のために利用方法が面倒になっているし、ドキュメンを参照せずに記述するのが難しいほど煩雑だ。

P0377R0: std::integral_constant with a Deduced Value Type

C++17の非型テンプレートの推定機能を使ったstd::integral_constantのエイリアステンプレート、std::constantの提案。

実装

template <auto V>
using constant = integral_constant<decltype(V), V>;

使い方

using answer = std::constant<42> ;

便利だ。悪影響もない。入るべきだ。

P0379R0: Why a joining thread from P0206 is a Bad Idea

デストラクターが自動的にjoin()を呼ぶスレッド、std::joining_threadが提案されているが、これは問題があるとする文書。

例えば、並列処理に使うスレッドを管理するために、std::vector<std::thread>に対してpush_backでstd::threadのオブジェクトを追加していくようなコードでは、push_backが失敗して例外が投げられると、std::threadのオブジェクトのデストラクターが走り、まだjoinableなのでstd::terminateが呼ばれる。

問題は、並列処理の最初ですべてのスレッドがお互いに最初に必要な処理が終わるのをロックで待っている場合、push_backが失敗しても処理が終わらないのでロックが解放されず、デッドロックになる。

デッドロックは未定義だが、std::terminateが呼び出されるのは十分に意味が定義されている。失敗するなら速いほうがいい。デッドロックよりはterminateが呼び出されるほうがいい。

ドワンゴ広告

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

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

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

2 comments:

Anonymous said...

ファイル展開リテラル??はちょっと雑ですね。まぁどうなんでしょ。バイト列で取れるんであればやっぱ配列としてほしいです。ポインタとしてもらうと長さが取れないのですごい不便だと思います。とあるsize()で取れないのであればそのバイト列はかなり危ない代物ではないでしょうか。

Anonymous said...

char8_tを用意するだけでなく、utf-8のファイルパスを受け取るとかostreamとか…と論文読んだら書いてましたね。
Windowsがデフォルトutf-8になるのは期待できそうにないので、そちらの策定をはやく進めてもらいたいものです。