2014-09-03

2014-07-post-Rapperswilのレビュー: N4090-N4108

N4090からN4108までの論文は、問題集であったり、文面案だったりするので、特に詳細に解説することはない。概要だけ紹介する。

[概要すら解説する気が失せるPDF] N4090: The Maladies of All Member Templates: An Incomplete Biography of Specialization (DR727 + DR1755)

すでに上がっている問題に、DR727DR1755とがある。これは、現在の文面の解釈が曖昧なため、コンパイラーごとにテンプレートの明示的特殊化(論文では、わかりやすさのために完全特殊化という言葉を使っている)、部分的特殊化の挙動が微妙に違う。この問題を解決するためにIssaquah会議で話し合った結果、意見の一致するルールが浮かび上がってきたので、そのルールを記載し、テストコードを示す。合意したルールの挙動にするClangのパッチも書かれたようだ。

N4091: C++ Standard Core Language Active Issues
N4092: C++ Standard Core Language Defect Reports and Accepted Issues
N4093: C++ Standard Core Language Closed Issues

C++のコア言語で認知されている問題、解決済みの問題、議論の結果、問題ではないとされた問題の一覧。

N4094: Response To: Let return Be Explicit

N4074で、return {expr}はexplicitを無視することが提案された。つまり、以下のようなコードが合法になる。

struct X
{
    explicit X(int) { }
} ;

X f()
{
    // C++14では違法
    // N4094提案では合法
    return {0} ;
}

N4094は、この提案に反論する論文である。

反論に用いている例がいろいろある。この解説ではかなり簡略化して解説するが、論文ではすこし違う例を出している。例えば、chronoライブラリだ。std::chrono::secondsで、ある数値を秒、分、時の単位で解釈して秒数を返す関数を考える。

enum struct unit { seconds, minutes, hours } ;

std::chrono::seconds
convert( unit u, int count )
{
    switch( u )
    {
        case unit::seconds :
            return { u } ;
        case unit::minutes :
            return { u } ;
        case unit::hours :
            return hours{ u } ;
    }
}

このコードは、enumによって、数値の単位を切り替えて秒数を返す関数である。しかし、このコードにはバグがある。case unit::minutesのところで、return { u }としてしまっている。std::chrono::secondsのコンストラクターはexplicitなので、C++14では、このバグはコンパイル時に検出可能である。しかし、N4074提案では、このコードはコンパイルが通ってしまう。そして、実行時に期待しない結果をもたらすだろう。

C++11が発行されてから、まだ3年しかたっていない。return {expr}という形は、まだ今から挙動を変更してもいいほど使われていないのだろうか。

しかし、ネット上で検索しただけで、実際に使っている例が見つかる。実際に使われているものの挙動を変更するのは危険だ。

N4074の発端になったtupleだが、return { 1, 2 }に対して、std::tuple< std::chrono::seconds, std::chrono::nanoseconds >が戻り値の型の場合、どうするのか。

std::tuple< std::chrono::seconds, std::chrono::nanoseconds >
test1()
{
    // 危険、単位が不明
    return { 1, 2 } ;
}

std::tuple< std::chrono::seconds, std::chrono::nanoseconds >
test2()
{
    // 安全、単位が分かっているので正しく変換される。
    return { 1h, 2ms } ;
}

N3739では、Perfect Initializationと呼ばれる技法を利用したtuple側による対応により、test1は弾くがtest2は通すようにできる。これは理想的である。N4074提案は危険である。

そもそも、戻り値の型とreturn文とが、どちらも同じプログラマーの管理下にあるということは断定できない。

// 誰か他人が書いた関数
SafeData GetSomeData() ;

// 安全なデータは暗黙の型変換を許し
// 非安全なデータは明示的な型変換を要求するクラス
struct SomeClass
{
    SomeClass( SafeData ) ;
    explicit ( UnsafeData ) ;
} ;

SomeClass f()
{
    return { GetSomeData() }  ;
}

この場合、GetSomeDataという関数の戻り値の型が変えられたとすると、C++14ならばコンパイルエラーになってくれるが、N4074提案では、コンパイルが通ってしまう。そして、実行時に期待しない結果をもたらすだろう。

スマートポインターと組み合わせるのも危険だ。そもそも、C++14では、newなど使わない。make_uniqueやmake_sharedを使う。そういうレガシーなコードとのやりとりのために、型安全性を犠牲にしてよいわけがない。

そもそも、{}を使うと暗黙に型変換するというのは、一貫性に欠ける。リスト初期化では、narrowing conversionを禁止しているではないか。

char f()
{
    int x = 0 ;
    return { x } ; // ill-formed、intからcharへのnarrowing conversion
}

このように、{}を使う文法で暗黙の型変換に制限しておきながら、他方で緩めるとは一貫性に欠ける。

論文ではこれらの例を挙げて、N4074提案に反対している。

N4095: File System TS Active Issues List (Revision R2)
N4096: File System TS Closed Issues List (Revision R2)
N4097: File System TS Defect Report List (Revision R2)

File System TSに持ち上がっている問題、議論の結果問題ではないとされた問題、解決された問題の一覧。

N4098: File System TS Editor's Report

File System TSの編集者による最新のドラフト、N4099に対する変更報告書。

N4099: Draft Filesystem Technical Specification

File System TSの現時点での最新のドラフト文面。

File Systemは、ファイルシステム、つまりファイルやディレクトリなどの列挙や操作を行うライブラリである。

[PDF注意] N4100: Programming Languages — C++ — File System Technical Specification

File System TS。

N4101: C++ Standard Evolution Active Issues List
N4102: C++ Standard Evolution Completed Issues List
N4103: C++ Standard Evolution Closed Issues List

C++の新機能に持ち上がっている問題、解決済みの問題、議論の結果問題ではないとされた問題の一覧。

N4104: Technical Specification for C++ Extensions for Parallelism, Working Draft,

STLのアルゴリズムに並列実行版を追加するParallelism TSのドラフト。

[PDF注意] N4105: Information technology – Programming languages, their environments and system software interfaces – Technical Specification for C++ Extensions for Parallelism

Parallelism TS。

N4106: Parallelism TS Editor's Report, post-Rapperswil

Parallelism TSの編集者による変更報告書。

N4107: Technical Specification for C++ Extensions for Concurrency, Working Draft

std::futureの機能を拡張するConcurrency TSのドラフト。

N4108: Concurrency TS Editor's Report, February 2014

Concurrency TSの編集者による変更報告書。

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。

今日は、社内でビブリオスというドラフトゲームを行った。社内にビブリオスをインストできる人間がいたので助かった。このビブリオスはドワンゴの社内同好会であるボドゲ部の部費で購入したそうだ。

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

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

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

1 comment:

Anonymous said...

N4094については、暗黙のダウンなんとか的な動作だけ規制すればいいかなーと思います。
単位不明については、C言語でよくあることなのでみんな身についてると思うのですが。
そんなこと言ってたら、メトリック型について全部規定する気ですか?
それはそれで理想ですけど誰がやるんですか?俺はヤです。
メトリック型については、ユーザー定義リテラルがそろわないと何とも言いようがないですね。
ただ、リスト返しは有用なのでいい着地点を見つけてほしいです。