2014-07-26

ロスレス圧縮アルゴリズムの歴史

History of Lossless Data Compression Algorithms - GHN: IEEE Global History Network

ロスレス圧縮アルゴリズムの歴史がまとめられている。

かなり長いので、詳細はリンク先を参照。

読み終わった感想を一言だけ言うと、特許のせいでいくつものアルゴリズムが発展せずにそのまま死んだということだ。特許は技術革新を阻害している。

キャンプの計画は難しい

この夏はキャンプにでも行きたい。キャンプに行きたければ、自分で企画するのが確実である。しかし、キャンプの企画は難しそうに思える。

まず、告知して人を募集しなければならない。そして、キャンプ場を予約する必要がある。キャンプ場までの移動手段も確保しなければならない。結構面倒な作業が必要そうだ。

キャンプ場では、ロッジのような出来合いの家を借りるのが一番手っ取り早い。クーラーやキッチンも設置されているし、言うことがない。しかし、それは面白いと言えるのだろうか。かといって、テントを設置するとなると、今の時期はとてつもなく蒸し暑くなるだろう。人が増えれば増えるほど不快になっていく。テントを設置する場合は、春か秋にしたほうがよさそうだ。

費用は、10人から20人ほど入れるロッジで、だいたい一日5,6万円ぐらいのようだ。これを10人から20人で割れば、まあ、費用としてはそれほどかからない。後は食材費や交通費ぐらいだろう。

残念ながら、キャンプ場というのは、かなり早めに予約しておかないと、予約で埋まる。二ヶ月ぐらい余裕をもっておいたほうがいいだろう。

2014-07-25

PHPの次のバージョンはPHP 7かもしれない

PHP: rfc:php6

PHPの次のバージョンは、PHP 6ではなく、PHP 7となる可能性があるとのこと。

敬意を説明すると、PHP 6は、次のPHPのメジャーリリースとして、2005年から盛んに開発されていたが、2010年にUnicode実装の難しさから頓挫した。言語でUnicodeを直接サポートする以外のPHP 6向けの機能は、大方PHP 5.3か5.4に取り込まれた。

この経緯のため、既存の多くのドキュメントや参考書などが、すでにPHP 5.xに存在する機能をPHP 6にやってくる新機能として紹介している。このままPHP 6を出すと、すでにPHP 6であると喧伝されているものとはことなるので、利用者が混乱するのではないか。

そういう理由で、PHPではバージョン番号6をスキップして7に行く議論があるそうだ。

ドワンゴ広告

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

そういえば、今日はある有名なドワンゴ社員が社内IRCにURIエンコードされたJPEG画像を発言していた。ドワンゴ社員ともなると、BASE64の脳内デコードはおろか、JPEGの脳内デコードもできるものらしい。

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

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

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

Linuxカーネルのバグをgit bisectで特定する話

Odd Bits - Tracking down a kernel bug with git bisect

Linuxカーネルのバージョンを3.15に上げたところ、Docker内でのsuやrunuserが謎のシステムエラーで動かなくなった。カーネルのバージョンを3.14に下げると問題なく動作する。明らかにカーネルが影響を及ぼしている。

よろしい、ならばgit bisectだ。git bisectは良いコミットと悪いコミットの間をバイナリサーチして、問題を引き起こしたコミットを見つけてくれる。

しかし、Linuxカーネル3.14と3.15の間には、約15000件のコミットがあるので、git bisectを手動で回すのは現実的ではない。

git bisectには、自動化のための仕組み、git bisect runがある。これは、コミットをチェックアウトした後に、自動でスクリプトを実行して、現在のコミットが良いか悪いか判断してくれる。したがって、自動化するスクリプトさえ書けば、あとは自動でgit bisectを走らせておけるはずだ。

とはいえ、結構面倒だったという。

まず、コミットが良いか悪いか判断するには、現在のコミットのLinuxカーネルをコンパイルして、実行して、Dockerを実行できるほどには構築されたシステムを立ち上げ、Dockerを実行してその中でテストを実行し、その結果を何とかしてビルド環境まで伝えなければならない。docker pullも行うので、ネットワークも必要だ。

元記事の筆者は、何とかしてその自動化環境を作り上げた。

さて、しばらく実行すると、git bisectは悪いコミットを特定したのだが、残念ながら、そのコミットは多数の変更を含むマージコミットだった。確かに、問題をもたらしたコミットには違いないのだが、まだ本当のコミットを特定できたわけではない。

そんなわけで、そのマージに含まれるコミットに対してさらにgit bisectをかけると、問題のコミットが見つかった。

問題の詳細としては、これはユーザースペースのソフトウェアの挙動に変化をもたらすものではあるが、権限の有無の問題であるので、Docker側を直すほうが望ましいとのことらしい。

ドワンゴ広告

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

N4036があまりにも読みづらい自己満足レイアウトを利用しているので読む意欲が保てず、気分転換に最近読んで面白かった記事を紹介した次第。

そういえば、Ubuntuにはrunuserがないのだな。suで代用できるか。

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

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

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

2014-07-24

Pixivに会社見学に行ってきた

とあるきっかけでpixiv社員と知り合ったので、この機会に、Pixivに会社見学をしてきた。

Pixiv社内は、大変にカラフルな環境であった。レゴブロックの形を模した椅子があり、レゴブロックのように積み重ねることができた。

また、机も変わっていて、すべての板がつながっている不思議な配置になっていた。

また、社内には、大昔のゲーム販売店の展示用の巨大なゲームボーイや、任天堂からゲーム販売店に送られた送り状が貼り付いたままのバーチャルボーイが置いてあった。筆者は、当時バーチャルボーイの店頭デモをプレイしたことがある。当時の感想は、残念、の一言に尽きる。

また、Pixivの入り口は、全面的に絵馬が貼り付けてあり、訪問者による絵やメッセージが並んでいた。これは粋な入り口だ。Pixivが提供するサービスと合致していて、実にいい入り口だ。

絵馬に描かれた絵には様々なものがあったが、いったいどうやってこれを描いたのかと疑問に思うほど技巧的な絵もあった。

あるドワンゴ社員の絵馬もあった。Pixivには日々お世話になっているのであろう。

筆者も、C++ Evangelist 江添亮と書き付けておいた。

技術的な話もしたが、PixivはC++は使っていなかった。

ところで、Pixivといえば、初期は社内の一角にメタルラックにマザボやHDDを無造作においたものがPixivを動かすWebサーバーだったそうだが、今はさすがにそうではない。しかし、メタルラックにマザボやHDDを無造作に置いたサーバーは、今のPixivにも存在していた。何でも社内のサーバーとして使われているそうだ。文化が残っているのは面白いことだ。

ドワンゴ広告

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

なぜ昨日のドワンゴ勤務中にこの記事を書かなかったかというと、メガネを忘れたからである。帰宅してから当日中に書くという手もあったが、しかし、すでにPixiv社内で、ドワンゴ勤務中にPixiv訪問ブログを書くと言った手前、やはりドワンゴ勤務中に書くことにした。

ところで、後でドワンゴ社内で聞いた話によると、Pixivにはドワンゴのポーカー部の絵馬もあるという。なんと、それは気が付かなかった。

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

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

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

2014-07-21

最近の動向

どうも、先週の月曜日から火曜日にかけて、午前3時頃まで起きていたのが災いしたのか、体調を崩してしまった。その週は、なぜかすこし疲れやすいぐらいの感覚だったのだが、金曜日には明らかに体調に不調を自覚するほどであった。

しかし、不調とはいえ、わずかな頭痛と熱とノドの痛みだけで、体はだるくないし、特に横になる必要も感じない。なかなか変な体調の崩し方をしたものだ。それでも、体調がよろしくないことは確かなので、この三連休は、運動をせずになるべく寝ていた。

さて、月曜日になって、だいぶ体調がよくなったので、たまには最近の自分のことでも書くことにする。

まず、何故か私宛に足袋が届いた。アマゾン経由ではないようだが、誰かが私に送ってきたらしい。雪駄はすでに持っているので、ちょうどいい。

また、最近、新しい料理に挑戦した。豆料理を作ろうと思い、大豆を1kg買ってきて水煮した。

大豆は主に、トマト煮に使った。トマト煮には、大豆の他にも、玉ねぎと人参をいれた。また、ひき肉も入れるとうまい。

それでもどうしても大豆が余ったので、さいごにひじき煮を作った。大豆とひじきと人参をだし汁で煮詰めると出来上がる。やや味付けが濃かったが、初めてにしては上出来と言えるだろう。油揚げを入れてもよかったかもしれない。

ところで、最近、ミートソースを作る機会が多い。ミートソースは、玉ねぎ、人参、セロリをみじん切りしてそれぞれフライパンで炒める。ひき肉も十分な量を炒める。1kgの大きなホールトマト缶を使い、十分に水分がなくなるまで煮込むと、うまいミートソースになる。十分に煮こむのは重要だ。ミートソースは、普通に作れば普通にうまい。一度自分でミートソースを作ると、出来合いのミートソースが食べられなくなる。それにしても、何故東京にはまともなミートソースを出す店に、未だに巡りあえていないのだろうか。

また、最近作った料理としては、白和えがある。白和えというのは、ほうれん草とか水菜とか人参などの野菜に、潰した豆腐を混ぜて、だし汁で味付けするだけの簡単なものだ。美味しいのだが、どうしても作ると量が多くなってしまう。

今回の三連休は、あいにくと体調を崩していたのであまりはかばかしいことはできなかった。なにか新しい料理にも挑戦したかったし、せっかくなのでどこかに遊びに行きたかったのだが、体調が悪くて終日寝ていた。

2014-07-18

2014-05-pre-Rapperswil-mailingのレビュー: N4021-N4029

5月分の論文集も、これで残すところあと21本だ。ただし、7月分の論文集が69本控えている。

[重量級PDF] N4021: A Proposal to Add 2D Graphics Rendering and Display to C++

C++1yに2Dグラフィックライブラリを入れる提案論文。

グラフィックは今や日常のプログラミングに必要である。グラフィックを描画する方法は、標準で用意されているべきである。

現在の提案では、既存のcairoの設計を元に、C++風の変換をして、またインターフェースを現代的なC++に手直しして使うことになっている。

新規のAPIを設計するのはとても手間がかかる。実験的な実装をして、実際に検証する手間は莫大だ。そこで、既存の、すでに実装されていて、実績もあるcairoライブラリを土台にする。

あらゆるプラットフォーム向けのすべての機能を規格化することはできない。そこで、std::threadと同じ手法を取り、ネイティブなハンドルを取得する方法を規定することにした。これにより、C++利用者は、実行環境に依存する機能も使うことができる。これは、すべてが実行環境に依存するライブラリを使うよりよほどいい。

context型とsurface型を統一することにした。surfaceというのは、描画ターゲットであり、画面とか純粋なメモリ領域とか、あるいはファイルや出力ポートといったたぐいのものだ。surfaceへの描画は、contextを経由して行われる。これは、古典的なグラフィックAPIによくある設計だ。しかし、果たして現代でも理にかなった設計であろうか。

contextは、リソースを共有でき、大昔は、メモリの節約に役立つ設計であっただろう。しかし、今では事情が異なっている。

cairoでは、contextは、既存の別のsurfaceに関連付けることはできない。surfaceからcontextを作成すると、contextの寿命は、その作成元のsurfaceに一生紐付けられる。つまり、利用者の視点からすると、わざわざsurface型とcontext型が分離している意味がない。surface型を直接操作すればいいのだ。

そこで、この論文では、context型とsurface型を統一することを提案している。

論文では、ほとんどの型はムーブしかできず、またimmutableな設計を提案している。これは、土台となるcairoが、Cによる明示的なリファレンスカウントという設計であるためで、しかも、GPUリソースというのは極めてコピーが高くつくので、ディープコピーは推奨できない。このライブラリは初心者でも簡単に使えるようになるべきで、そのためには最初からコピーが禁止されていたほうがよいとしている。

なお、この論文では、提案は現時点ではTSを目指しているとのことだ。

N4022: A proposal to add a generalized callable negator (Revision 2)

Negator、つまり、任意個の実引数を転送して、結果を否定する関数オブジェクトのラッパーである、not_fnの提案。

従来のnegatorであるnot1やnot2は、一個、二個の実引数しか転送できなかった。しかも、予め定められたネストされた型名が必要などの制限が強かった。

// 従来の使いづらいわけのわからない意味不明なコード
struct Yes : std::unary_function< int, bool >
{
    bool operator ()( int ) const
    {
        return true ;
    }
} ;

int main( )
{
    auto f = std::not1( Yes{} ) ;
    std::cout << f(0) << '\n' ;
}

これが、以下のように書ける。

// まともでわかりやすくてモダンなC++風のコード
bool yes( int, int, int, int, int )
{
    return true ;
}


int main( )
{
    auto f = std::not_fn( &yes ) ;
    std::cout << f( 1, 2, 3, 4, 5 ) << '\n' ;
}

ああ、可変引数とムーブセマンティクス万歳。

N4023: C++ Extensions for Library Fundamentals, Working Draft

C++の標準ライブラリに対する拡張的な変更の文面ドラフト。これはTechnical Specificationのようなので、これが規格に直接反映されるよう提案されているわけではない。

[PDFとそれ以外のまともなフォーマットも区別すべき] N4024: Distinguishing coroutines and fibers

コルーチンとファイバーの違いを解説している論文。

これから提案されるファイバーとはなにか。コルーチンとはどう違うのかをわかりやすく簡潔にまとめている。

知っている人にはイマサラ何を初歩的なことを言うかという論文のようにみえるかもしれないが、フルスタックエンジニアなど幻想であり、プログラミングの分野があまりにも広いので、C++WG論文にはよく、提案されている技術の初歩的な解説論文も上がる。とてもわかりやすく書かれているので、読むといい。

ファイバーとは、カーネルスレッドの上に構築されるユーザースペースの実行単位のことで、その設計は、可能な限りstd::threadに似せている。ファイバー用のmutexやcondition variableもある。ひとつのスレッドの上で動く複数のファイバーは、協調的なマルチタスクを実現する。

ファイバーのスレッドに対する優位点は、コンテキストスイッチにカーネルを経由しないので、スレッドより高速に実行できる。

しかも、同じひとつのスレッド上で動く複数のファイバーは、同時に実行されることはないので、お互いに競合しない。これは、ひとつのスレッド上の複数のファイバーで共有するデータをロックしなくてもいいということを意味する。

もちろん、欠点もある。スレッドは規格上、いずれ必ず実行が進むという強い保証を与えられている、ファイバーには、そのような強い保証はない。あるファイバーが実行を握ってしまえば、同じスレッドの他のファイバーは実行できない。また、ファイバーがスレッドをブロックする操作を行った場合も同様だ。

これに比べて、コルーチンとは、関数を拡張したものである。したがってそのインターフェースはスレッドに似ておらず、関数の拡張である。コルーチンは中断した関数の実行を継続させるだけで、ユーザースペースのスケジューラーなどはない。

将来提案される予定のファイバーは、Boost.Fiberを元にしている。これは、Boost.Coroutineを使って実装されている。論文では、ファイバーを使ってコルーチンを実装する形もありだとしている。

[PDFを探求する気はない] N4025: Exploring classes of runtime size

さて、これをどこから解説すればいいものか。

この提案論文は、実行時束縛配列データメンバー(runtime bound array data member)という、クラスのデータメンバーとして実行時にサイズが決まる配列を宣言できるようにする提案である。N3875提案とは異なり、そのようなクラス(実行時サイズ型)は、動的ストレージ上にも確保できる。


struct runtime_size_type
{
    std::size_t const array_bound_size sizeof ;
    char array[ array_bound_size ] ;

    runtime_size_type( std::size_t size )
        : array_bound_size( size ) 
    { }
} ;

int main()
{
    runtime_size_type t1(10) ; // OK
    new runtime_size_type(10) ; // OK
}

動的ストレージにも確保できるようにするためには、実装可能な方法で設計しなければならない。今日のC++では、クラスサイズというのは、固定である。sizeof(T)の結果はコンパイル時に決定でき、実行時に必要な処理は何もない。しかし、クラスのサイズが実行時に決まる場合、この常識は忘れなければならない。

論文では、実行時にサイズがきまる型(runtime-size type)を動的ストレージ上に確保する方法として、三段階の手順を提案している。

  1. オブジェクトが必要とするストレージのサイズを決定する
  2. メモリーを確保する
  3. コンストラクターを呼び出す

提案論文では、コンパイラーがオブジェクトのサイズを返す最小の「size関数」を生成できるようにしている。

実行時にサイズが決まる配列のデータメンバーを、実行時束縛配列データメンバー(runtime bound array data member)という。実行時束縛配列データメンバーの添字に与える式を、束縛式(bound expression)という。実行時束縛配列データメンバーの束縛を決めるために使われるデータメンバーを、配列束縛データメンバー(array bound data member)という。


struct X
{
    const std::size_t a sizeof ; // 配列束縛データメンバー
    char b // 実行時束縛配列データメンバー
    [ a ] // 束縛式
    ;
} ;

配列束縛データメンバー、実行時束縛配列データメンバー、束縛式には、それぞれ厳しい制約がある。

束縛式に使えるデータメンバーは、配列束縛データメンバーしか認められない予定で、配列束縛データメンバーは、配置アドレスの低いほうが高い方にアクセスすると未定義とか、配列束縛データメンバーや束縛式が複数回の評価で結果が変わると未定義とか、とにかく制限が多い。

このような厳しい制限によって、コンパイラーはコンストラクターからオブジェクトのサイズを決定するためだけのsize関数を切り離して生成できる。size関数は未規定の回数呼ばれる。

実行時サイズ型をデータメンバーとすることはできる。実行時サイズ型の実行時束縛配列は違法である。

sizeofは、実行時サイズ型に使うと違法である。実行時サイズ型のオブジェクトに対して使うと、そのオブジェクトの実行時のサイズを返す。

実行時サイズ型へのポインターと整数との間の演算は、単項+演算子を除いて、禁止される。単項+演算子が許されている理由は、特に実装上の問題がなく、また禁止する理由もないためだ。

unionをサポートするべきかどうか議論があるが、std::dynarryの自然な実装には実行時サイズ型であるunionを使うので、サポートされていたほうがいいのではないかとしている。

実行時サイズ型をplacement newすることは、当然可能である。もちろん、利用者は十分なサイズのストレージを提供する責務を追っているわけだから、自己責任だ。ただし、すでにコンパイラーによってsize関数が通常のコンストラクターとは分離して生成されているわけだから、あらかじめ必要なサイズを計算するために、size関数を呼び出す方法が提供されていてしかるべきではないか。たとえば、sizeofに実行時サイズ型の直接初期化式を書けば、実行時にsize関数だけが呼び出されるなどの文法はどうか、と論文は書いている。

グローバル変数に実行時サイズ型は、実装可能であるが、より深い考察が必要であるとしている。

テンプレートの存在は、実行時サイズ型に特に影響しない。ただし、従来、あらゆる型に対して合法であった、sizeof(T)という式が、実行時サイズ型の出現によって、違法になってしまう。そのため、型が実行時サイズ型かどうかを調べるtraitsが必要だろう。なお、このtraitsは、そもそもsizeofが違法になるのだから、コンパイラーマジックを必要とせずに、SFINAEによって容易に書くことができる。

なぜこんなややこしく、明示的に配列束縛データメンバーを書かせるのかというと、配列のサイズを格納するデータメンバーを暗黙に生成すると、ユーザーの自由度が損なわれるからだ。例えば、二つの同じサイズの実行時束縛配列データメンバーが欲しい場合、以下のように書ける。


struct X
{
    const std::size_t bound sizeof ;

    char a[bound] ;
    char b[bound] ;

    X( std::size_t size )
        bound( size )
    { }
} ;

もしコンパイラーが愚直にそれぞれの実行時束縛配列データメンバーに対して、暗黙にboundのようなサイズ情報を格納するデータメンバーを定義してしまうと、このような自由度が損なわれてしまう。

この論文を読み終えた筆者の脳内に思い浮かんだセリフとしては、「C++はエキスパートに優しくなりすぎた」というあのBSの発言だ。

N4026: Nested namespace definition

ネスト名前空間定義の提案。

// N4026提案
namespace A::B::C 
{
// ...
}

このコードは、以下のコードに等しい。

// 現在のC++
namespace A {
    namespace B {
        namespace C {
// ...
        }
    }
}

論文は、既存のC++ユーザーがstack overflowのような質問サイトで、ネストされた名前空間をもっと簡単に書く方法はないのかという質問が複数あることを引用して、この文法は、現実にプログラマーの要求があることを示している。また、大きなプロジェクトでは、名前空間が深くネストするのはよくあることである。

これによく似た文法は、C#に存在して、実際に活用されている。

Using Namespaces (C# Programming Guide)

また論文では、現時点でこれを実装しているコンパイラーは知らないものの、Lazy C++という既存のツールが、この変換を行うとして紹介している。

lzzはなかなか面白そうなツールだが、そのような外部ツールの変換に頼ると、ビルドプロセスが複雑になるため、やはり言語に取り入れることが望ましい。

これは一見小粒にみえるシンタックスシュガーだが、ドワンゴ社内でこの提案を紹介したところ、ドワンゴ社員は欲しいと言っていた。

[やる気をそがれるPDF] N4027: Type Member Property Queries (rev 2)

静的リフレクションとして使えるtraitsの具体的な設計の提案。全部を紹介していてはキリがないが、たとえば、

// N4027提案
enum struct E { hoge, hage, fuga } ;

int main()
{
    // 3
    std::enumerator_list_size<E>::value ;

    // "hoge"
    std::enumerator_identifer<E, 0>::value ;

    // hageの値
    std::enumerator_value<E, 1>::value ; 
}

文字列は、text_constantという、定数式で文字列を返すクラステンプレートによって返される。

他にも、クラスのアクセス指定やメンバーの数や名などを得ることができる。

[PDFは扱いづらい] N4028: Defining a Portable C++ ABI

ポータブルABIを規定しようという提案。

これは・・・微妙。いかにもMicrosoftらしい提案と言える。

C++には安定したABIがない。バイナリから外部に公開するインターフェースとしてC++のコア言語機能や標準ライブラリを使うことは、様々な問題がある。

たとえ同じプラットフォームであっても、同じコンパイラーの同じバージョンの互換性のあるコンパイルオプションでなければ、バイナリに正常にリンクできる保証はないからだ。

このために、未だに公にするAPIとしては、C言語を使うことが一般的である。これは極めて悲惨なことだ。Cは型安全でもメモリ安全でもないため、プログラマーはポインターとサイズのペアなどを直接扱わねばならず、極めて間違いの発生しやすい非人間的な作業を強いられる。

COMやCORBAのようなヘンテコな独自仕様が蔓延しているのも、結局、クラスとかvirtual関数を、なんとか安定したABIで使いたいからである。

そこで、ABI安定なコア言語と標準ライブラリを実装依存として規程しようではないか。ABI互換なコア言語は、extern "abi"{ ... }で囲むことで得られる。また、ABI互換な標準ライブラリは、std::abi下に用意しよう。std::abiはstdとほぼ同じであるが、今後のABI非互換な変更はない。

これは、ひとつのコンパイラーの中にバージョンの異なる二つのコンパイラーを内在させ、またバージョンの異なる二つの標準ライブラリを切り替えられることと、何が違うのか。

今はいい。いまのstd::abiは、現在の最新のスナップショットだから、stdとの差はない。しかし、今後標準ライブラリに変更が加えられるにつれ、どんどん差が開いていく。断絶していく。

この提案は、長期的に見れば、確実に負債になる筋の悪い提案である。昔のバージョンのソフトウェアをそのまま使い続けるのと同じ愚行である。

そもそも、バイナリ互換性などそこまでして必要なものか。ソースコード互換性さえあれば足りるではないか。

GCCは、ABI互換性を重視し過ぎるあまりに、GCCは4.9になってもstd::stringがいまだにCopy On Writeだそうだが、それはGCCの意思決定プロセスの問題に思われる。Microsoftがメジャーアップデートごとに互換性を壊してDLL地獄に陥っているのも、やはり彼らの戦略上の問題だ。

中庸を取れないからと言って、この提案は筋が悪すぎる。このような提案に賛同する者は、Visual C++ 6.0でも使っていればいいのではないだろうか。少なくとも安定したABIは得られるであろう。

筋が悪すぎる。長期的にみれば確実に負債になる。何を考えているんだこの提案は。

[最後までPDF] N4029: Let return Be Direct and explicit

何やら格調高い題名の提案論文。

return文は特別である。return文のオペランドから関数の戻り値の型への変換は、暗黙に明示的変換にしようという提案。

以下のコードが合法になる。


struct X
{
    explicit X( int ) ;
} ;

X f()
{
    // 現在のところill-formed
    // N4029提案ではwell-formed
    return 0 ; 
}

これ以上言うことがない。return文に限り、暗黙に明示的変換される。

論文では、戻り値の型はすでに関数宣言に明示的に記述されているのだし、return expr ; という式は、明らかに、戻り値の型をexprで初期化するものであるので、returnは特別扱いしてもよいとしている。

また、上記のコードのコンパイルエラーは、「俺はお前が何をやりたかったのか知ってるよ。俺のエラーメッセージはほれ、何を書けばよかったのかすら出力してるよ。でも、お前が手で書け」となるので、プログラマーはそんな忌々しいエラーメッセージなど見たくはないだろうと、論文には書かれている。

筆者としては、どうもこれは筋が悪いように思われる。やはり明示的な型変換が必要な場合は、明示的に型変換を書かせるべきであると思う。

ドワンゴ広告

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

先日、ドワンゴが主催した社内ポーカー大会で、宗教戦争を引き起こす悪意ある目的で、きのこの山とたけのこの里を設置したところ、たけのこの里が多数派であり、実際にたけのこの里の方が先になくなった。これは解せないことである。きのこの山はパリパリ香ばしいクラッカーと塊のチョコレートが魅力的である。一方、たけのこの里はパサパサとした舌触りの悪いクッキーに申し訳程度にコーティングされたチョコレートという始末。どう考えてもきのこの山に圧倒的軍配が上がるべきものであるはずなのだが、世の中は不条理に満ちている。

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

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

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

2014-07-16

シンガポールの問題ギャンブル国家委員会のワールドカップサッカーでドイツに息子の貯金を全部賭けた啓蒙広告、コメディに終わる

シンガポールの、問題ギャンブルに対する国家委員会(National Council on Problem Gambling)では、ワールドカップに合わせて、ギャンブルによる不幸を啓蒙するための広告を流していた。この広告はシンガポールの国営放送で流されたので、シンガポール人の大半は見たという。

Hey! Guys! Guys! I really can't wait for the World Cup. Who do you think is gonna win it?

My dad said Brazi will win.

No, no, no!, Argentina's gonna win. Because Messi will dribble past everyone.

I wish Spain will win. My whole family supports them.

How about you Andy?

Andy: I hope Germany will win.

Why?

My dad bet all my savings on them.

[Caption]: Often, the people who suffer from probem gambling aren't the gamblers.

[Caption]: Kick The Habit. Stop Problem Gambling.

おい、お前ら、お前ら。オレ、ワールドカップ楽しみだぜ。どこが勝つと思う?

オレのパパはブラジルが勝つって言ってたもんね。

いや、いや、いや。アルゼンチンが勝つに決まってんだろ。メッシがドリブルで全員抜き去るからよ。

スペインに勝ってほしいな。ボクの家族みんなが応援しているんだ。

アンディはどう?

アンディ「ドイツが勝って欲しい」

なんで?

アンディ「パパがボクの貯金を全部賭けちゃったんだ」

キャプション:問題あるギャンブルで被害を被るのは、ギャンブラー以外の人たちである。

キャプション:悪習を断て。問題あるギャンブルをやめよ。

このNCPGによる啓蒙広告は、ワールドカップの優勝結果が決まる前に放送されたので、結果次第ではコメディになってしまうというコメントがあった。

残念ながら、2014年のFIFAワールドカップの結果は、ドイツの優勝で終わってしまったので、この動画はコメディになってしまった。

YouTubeでは、いい投資をしたとか、パパは賢いとか、ギャンブルを始めてみようかな、とかいった皮肉のこもったコメントがあふれている。

NCPGはワールドカップの結果を受けて、以下のようなバナーを用意した。

「お前のパパ勝ったんだろ。貯金返してもらったか?」

アンディ「ううん、パパはやめてくれないんだ・・・また賭けるんだってさ」

博徒が博打で得た金をまた博打につぎ込むのは、よくあることである。

余談だが、シンガポール英語の聞き取りは難航したので、英語に書き起こしておいた。おそらくあっているはずである。

2014-07-15

ドワンゴポーカー選手権

7月14日の夜に、ドワンゴ社内で、ポーカー選手権が行われた。社外からも人を招き、トロフィーを用意して、最強のポーカープレイヤーを決定する戦いが行われた。

ドワンゴには社内同好会としてポーカー部がある。ポーカー部では、トロフィーを用意して、定期的にポーカー大会を開いて、トロフィーを奪い合っている。ドワンゴのポーカー部員も大勢参加したのだが、残念ながら、皆負けてしまった。

こうして、ドワンゴポーカー部のトロフィーは、あわれにも社外のポーカー強者に掠め取られてしまったのであった。これで社外に流出したトロフィーは2つ目になる。ドワンゴのポーカー部員は奪還を息巻いているが、果たしてどうだろうか。

筆者はポーカーはとても弱いので参加せずに、早々に飛んだ落伍者の暇つぶしのために、ボードゲームをしていた。今回は、キャッスルクラッシュというゲームを行った。これは、積み木を破壊していくゲームであり、とても面白い。

ポーカー大会の後、ドワンゴ社員で人狼を行った。人狼とは、村人と人狼がいて、参加者の中から人狼を探し出すゲームである。人狼はその正体を隠している。毎日、話し合いを行ってから投票して、人狼だと疑わしき参加者を一人、血祭りにあげる。人狼をすべて血祭りに上げられれば、村人側の勝利。人狼と同数まで村人が減ってしまえば、人狼側の勝利となる。

筆者は、このゲームがあまり好きではない。ただ、食わず嫌いもどうかと思い、たまたま機会があったので、参加してみた。人狼であるかどうかは、なかなかわからないものだ。しかし、人狼は全員叩き潰さねばならない。そうしなければ村人は勝利できないからだ。

ところで、ポーカー大会の会場に、忘れ物の服が二着残っていた。ドワンゴ社員のものか、社外の人のものかは、まだわかっていないのだが、服の特徴はそれぞれ、

  • フード付き半袖シャツ
  • 黒と裏地が緑のベスト

だそうだ。心当たりのある方は連絡されたし。

ドワンゴ広告

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

ドワンゴには、ポーカー部以外にも、ボードゲーム部やカードゲーム部(MTGなど)がある。

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

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

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

2014-07-12

雑記

ふと気がつけば、もう東京に出てきてから半年たっている。早いものだ。

今年初めの引越と仕事は、筆者の身の上に大変化をもたらすことは予想していた。変化は好ましいことである一方、悪い影響をももたらす可能性があるものだ。

東京に出てから、筆者はいつも以上に、規則正しい生活を心がけている。早寝早起き、食事、運動、休みの日は休む。健康的な精神を保つためには、まず健康的な肉体を保たねばならない。

現在の環境は、少なくとも数年は継続しなければならないのだ。僅かな短期的な作業のために、徹夜などをして心身を潰してしまってはならぬ。

同時に、日常生活に刺激を与えるために、常に何らかの変化を試みている。料理、テント、ハンモックは、その変化の試みの一部だ。

ところで、昨日、ギークハウス秋葉原で、その場で焙煎して挽いて淹れたコーヒーを飲んだ。コーヒーとはこんなにもうまいものだったのかと感動した。やれやれ、本当にうまいコーヒーごときも知らないとは、まだまだ人生の経験が足りないとみえる。

今日は買い物がてら、12kmほど歩いた。今週は全然歩いていなかったので、いい運動になった。

2014-07-11

momonga.vim #6 ドワンゴ開催の告知

momonga.vim #6 in ドワンゴ(あきらかに) - connpass

@supermomongaの企画するもくもくVim会が、8月2日土曜日の午後に、ドワンゴのセミナールームで開催される。

もくもく会なので、皆でもくもくと何かしらVimに関する作業でもする集まりだ。

今回は、なんとあの暗黒美夢王が現れるとのことで、恐ろしさのあまり震えが止まらない。筆者のVim力では太刀打ちできそうにない。

ドワンゴ広告

この記事はドワンゴ退社後に書かれた。

今日、ドワンゴ社内ではA&Wルートビアが売りさばかれていた。社内にはルートビアがあればコードを書く速度が3倍になると豪語するほどのルートビア好きがいる一方、サロンパスの臭いを訴えて顔をしかめる人も多く、両極端であった。

ところで、ドワンゴ社内のテキストエディターのシェア率は、誰も詳しく統計を取っていないのでわからない。Vim利用者は相当の数がいるはずだが。

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

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

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

2014-07-10

2014-05-pre-Rapperswil mailingのレビュー

すでに2014-07 post-Raperswil mailingsが公開されているので、レビューを急ぎたいが、さっと読んで終わりにも出来ぬのが辛いところだ。

C++ Standard Evolution Active Issues List
C++ Standard Evolution Completed Issues List
C++ Standard Evolution Closed Issues List

C++の新機能の議論の場である。C++ Evolution Working Group(EWG)で、現在既知の問題、解決済みの問題、議論の結果問題ではないと結論された問題のリスト。

N4013: Atomic operations on non-atomic data

非アトミック型に対するアトミック操作を可能とする提案。

C++11とC11で標準化されたアトミック操作は、アトミック型のオブジェクトに対してしか行えない。オブジェクトはアトミック型であると明示的に宣言する必要がある。

アトミック操作できるオブジェクトを、型システムで管理するのは理にかなっている。標準規格で厳密に制定された挙動の保証を受けられるし、うっかり非アトミック操作してしまうことをふせぐことができるからだ。また、アトミック操作が不可能な場合をなくせる。例えば、アトミック操作をするオブジェクトは適切にアライメントされていなければならないアーキテクチャで、アトミック型ではないために、アトミック操作に必要な厳格なアライメントがされていない場合、アーキテクチャの制約上、アトミック操作はできない。何らかのロックを使って実装しなければならないが、それではアトミック操作の意味がない。

しかし、現実のコードは、C++11、C11以前から書かれているレガシーコードばかりである。ほとんどの既存のコードは、環境依存の方法(gccの__syncやMSVCのInterlockedなど)でアトミック操作を行っている。アトミック操作するオブジェクトは、宣言時に明示的にアトミック型であると宣言されてはいない。このような既存の莫大なレガシーコードを、すべてC++11やC11のアトミック型に移植するのはいかにも無理だ。

具体的な例としては、Linuxカーネルが挙げられる。リーナスはC11のアトミック操作モデルに対して反感を持っている。

ではどうするか。もちろん、一部の環境では、以下のようなコードが動くかもしれない。


int x;
reinterpret_cast<atomic<int>&>(x).fetch_add(1);

しかし、動くという保証はどこにもない。

そこで、この論文では、非アトミック型Tから、atomic<T>に変換できるかどうかを調べられる機能と、実際に変換する機能を、ライブラリとして追加する提案となっている。変換可能かどうか調べる機能は、type traitsで提供され(C11向けにヘンテコなプリプロセッサーマクロでも提供されるかもしれない)、変換機能は、関数テンプレートで提供される(C11向けにヘンテコなプリプロセッサーマクロでも提供されるかもしれない)

[論文のフォーマットはプレインテキストかHTMLに統一されて欲しい] N4014: Uniform Copy Initialization

この論文は、=に続く{ ... }という形の初期化子を、コピー初期化ではなく、直接初期化にする提案をしている。

以下の例を考える。

struct name
{
    explicit name( std::string const &, std::string const & ) { }
} ;

name n1 { "Nobuo", "Kawakami" } ; // OK
name n2 = { "Nobuo", "Kawakami" } ; // エラー

なんで?

n2がn1より危険であるという理由はどこにもない。n1が認められるのならば、n2も認められるべきである。

C++規格から言えば、n1は直接初期化なので合法だが、n2はコピー初期化なので違法となる。しかし、ソースコード上は=がついているかどうかという些細な違いでしかない。

ほぼすべてのプログラマーは、厳密な文法を理解した上でコードを書かないし、当然そうあるべきだ。その上で、多くのプログラマーが、上記のn2がコンパイルエラーになるという問題に出くわし、原因を調べるのに、無駄に時間を浪費している。この問題は、C++にリスト初期化が追加される以前から存在する問題である。C言語畑からやってきたプログラマーは初期化で{ }を使う前には=が必要だという先入観があるので、当然のように=を書いて、この問題にぶち当たる。

プログラマーの貴重な時間を、このような些細な文法上の問題で浪費させるべきではない。

この論文は、= { ... }という形のコピー初期化を、直接初期化と同じように扱う提案をしている。この提案の元では、上記のn2は合法となる。{ }以外の初期化子の挙動は変わらない。

explicitの機能が損なわれることはない。explicitは暗黙の型変換を防ぐ目的で、依然として機能し続ける。

[PDFは予期していない] N4015: A proposal to add a utility class to represent expected monad

optional<T>をより汎用化して、Haskellのモナド風味にしたライブラリ、Expected<E, T>の提案。

optional<T>は、T型か、あるいはT型を格納していないかというライブラリである。これはもう少し深く考えると、T型とT型を格納していないというエラーを示す型とのenumとなる。ということは、もっと汎用化できるではないか、すなわち、T型か、エラー型のどちらかを格納しているenumのような、もっと汎用的なライブラリがあればよいのだ。

ところで、エラー処理について考えてみよう。プログラムを実行中にエラーが起き、そのエラーを上位の呼び出し元に伝える場合の方法について考える。C++では、エラー処理の方法として、関数の戻り値と例外という、二つの方法がある。

関数の戻り値はC言語からある伝統的な方法だ。しかし、関数の戻り値という通信経路をエラー通知に専有されてしまうのは問題だ。しかも、関数の戻り値をいちいちにチェックしなければならず、甚だ面倒である。通常の処理とエラー処理を綺麗に分けることができない。

例外は、エラー通知専用の別の通信経路である。しかし、ある関数がどんな例外を投げるかどうかというのは、関数の宣言や呼び出しからでは分からず、コードを追っていかなければならない。さらに、例外は一旦エラー情報を保存していくとか、スレッドを超えて伝播させることが面倒だ。

この問題は、関数の戻り値と例外を両方使うライブラリによって解決できる。すなわち、結果を通知する値であるT型か、エラーを通知する値であるE型か、そのどちらかを格納するクラス、Expected<E, T>の提案となる。

より正確には、T型か、std::unexpected<E>型のどちらかを格納する。unexpectedというのは、TとEが同じ型であることを許容するためのタグ型である。

以下のコードは、典型的な、エラー通知を例外で行う関数である。

double safe_divide(double i, double j)
{
    if (j==0) throw DivideByZero();
    else return i / j;
}

となる。ゼロ除算を防ぐコードである。これを使う側のコードは、例えば以下のようなものになるだろう。


double f1 ( double i, double j, double k )
{
    return safe_divide( i, k ) + safe_divide( j, k ) ;
}

これをexpectedを使って書き直すと、

enum class arithmetic_errc
{
    divide_by_zero, // 9/0 == ?
    not_integer_division // 5/2 == 2.5 (which is not an integer)
};

std::expected<std::error_condition, double> safe_divide(double i, double j)
{
    if (j==0) return make_unexpected(arithmetic_errc::divide_by_zero); // (1)
    else return i / j; // (2)
}

となる。これを使う側のコードは以下のようになる。


double f1 ( double i, double j, double k )
{
    return safe_divide( i, k ).value() + safe_divide( j, k ).value() ;
}

expectedのメンバー関数valueは、値がある場合は値を、そうでない場合は例外を投げる。

値があるかどうか、明示的に確認することもできる。


double f1 ( double i, double j, double k )
{
    auto s1 = safe_divide( i, k ) ;
    auto s2 = safe_divide( j, k ) ;

    if ( s1 && s2 )
    {
        return *s1 + *s2 ;
    }
    else
    {
    // エラー処理
    }

}

さて、これをmonad風に書くとこうなるそうだ。


expected<error_condition, int> f(int i, int j, int k)
{
    return safe_divide(i, k).bind([=](int q1) {
        return safe_divide(j,k).bind([=](int q2) {
            return q1+q2;
            });
        });
}

これで、値がある場合は値を、値がない場合はexpectedをそのまま呼び出し元に返すようにできる。Haskell厨も大満足。めでたしめでたし。

C++では、lambda式の文法があまりにも冗長すぎるために、悲惨なコードになってしまっている。論文ではこの問題を解決するために、いくつか方法を提示している。

ひとつは、外部の関数としてmapを定義すること


expected<exception_ptr,int> f(int i, int j, int k)
{
    return map(plus,
        safe_divide(i, k),
        safe_divide(j, k) );
}

ただし、これは遅延評価されないし、何より評価順序が未規定である。

これを完全に解決するには、コア言語にHaskellのdo記法風の文法、do式を導入して、以下のように書けるようにすればよい。


expected<error_condition, int> f2(int i, int j, int k)
{
    return (
        auto s1 <- safe_divide(i, k) :
        auto s2 <- safe_divide(j, k) :
        s1 + s2
    );

これはexpected以外にも広く役に立つ。

この論文を読むのは疲れた。

[本記事最後のPDF] N4016: Light-Weight Execution Agents Revision 2

OSの提供するネイティブなスレッドよりは軽い実行単位を提供するライブラリの提案。

N4017: Non-member size() and more

タイトル通り、非メンバー関数としてのstd::size, std::empty, std::front, std::back, std::dataの提案。

たとえば、std::sizeは以下のように使える。


std::vector<int> v(10) ;
std::size(v) ; // v.size() == 10

なぜ必要なのか。可読性と安全性と効率と汎用性のためである。

このように非メンバー関数であれば、たとえば、配列にも使える。


int a[10] ;
std::size(a) ;

配列の場合は、以下のような関数テンプレートを書くことで、サイズを返すことができる。

template <class T, std::size_t N>
constexpr std::size_t size(const T (&array)[N]) noexcept
{
    return N;
}

これは、醜悪なマクロよりも安全だ。

非メンバー関数を使うことにより、様々な型が、共通の方法で操作できることになる。

std::sizeはstd::forward_list向けのオーバーロードがない。これは、多くの利用者はsizeが低数時間であることを期待しているが、定数時間で実装できないためである。

N4018: C++ Standard Core Language Active Issues
N4019: C++ Standard Core Language Defect Reports and Accepted Issues
N4020: C++ Standard Core Language Closed Issues

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

ドワンゴ広告

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

今日は台風なのでさっさと帰る。

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

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

cc by-nd 4.0: creative commons — attribution-noderivatives 4.0 international — cc by-nd 4.0

2014-07-07

Kickstarterでポテトサラダを10ドルでクラウドファンディングした者が、すでに8000ドルの出資を受けた話

Potato Salad by Zack Danger Brown — Kickstarter

クラウドファンディング用のWebサービス、kickstarter.comで、10ドルの出資を受けたならばポテトサラダを作るという触れ込みで出資を募った者が、すでに8000ドル以上もの出資を受けるという大成功を収めている。

ポテトサラダ

俺はポテトサラダを作るぜ

いや、俺は単にポテトサラダを作る予定だ。どういうポテトサラダを作るかはまだ決めてない。

追記:作った

目標を延長:

35ドル:俺は4倍のポテトサラダを作るぜ。40ドルとは10ドルの4倍ではないが、まあ、出資者への感謝の気持を込めて。

75ドル:ピザパーティ!

100ドル:2種類のポテトサラダのレシピを試すぜ

追記2:報道すべき価値のあるポテト

http://www.cnet.com/news/guys-kickstarter-dream-making-potato-salad-possibly-with-dill/

追記3:ワーオ、お前ら最高だぜ

進捗最高だぜ。こりゃもう帽子をつくるしかねーな。帽子が欲しい人向けに出資枠を増やしたぜ。帽子の見た目に興味がある奴は以下を見れ。

http://www.zazzle.com/i_love_potato_salad_mesh_hat-148005376484063142

目標を延長:

250ドル:高品質のマヨネーズ(自然食品から選ぶぜ)

300ドル:コックを読んでレシピを教えてもらう。

350ドル:もっとポテトサラダを作るのと、あとたぶん3種類目のレシピに挑戦

ニュースになったぜ!

http://www.abc6onyourside.com/news/features/top-stories/stories/mans-potato-salad-plea-takes-off-kickstarter-33010.shtml

新たに目標を延長:

1000ドル:ポテトサラダ作成をストリーミング放送する。

1200ドル:出資者に感謝の意を伝えるための動画を撮影するために人を雇う

延長大目標:

延長して設定した目標を次々に達成していっちまった。もうこれ以上なにをすればいいのかわかんねーや。とりあえず目標額を倍にするしかねーよな?

3000ドル:俺のキッチンは狭い。パーティホールを貸しきってネット民をみんな招待するぜ!(キッチンに入れるのは10ドル以上出資したやつだけな)。ネット民はポテトサラダを愛しすぎだろ。ポテトサラダもネット民を愛していることをみせつけてやろうぜ!!

なんともまぁ。

まあ、kickstarterでよくあるクラウドファンディングの趣旨からは、だいぶ外れる気もするが、コメディアンとしてはとてもおもしろい。金を出資するだけの価値は十分に生み出していると言えよう。

2014-07-05

Qualcommが謎のDMCA取り下げ通知を発行

[Phoronix] Qualcomm DMCA Notice Takes Down 100+ Git Repositories

QualcommがGitHubの100件以上ものレポジトリのファイルに対して、DMCA取り下げ通知を発行したそうだ。

まあ、それが実際に著作権侵害なのであればいいのだが、どうやら報告によると、単にQualcommの著作権表記の文字列だけを検索して機械的に通知を出したと思われる節があるらしい。多くのファイルは、公に公開されているリファレンスコードやサンプルコードだ。まあ、これはまだ著作権を主張するのもわかるが、androidカーネルのソースファイルと同等のものも取り下げられたらしい。ソースファイルには"Qualcomm Confidential and Proprietary"と書いてあるものの、すでにLinux財団の管理下にあるはずのソースコードだという。

Qualcommも映画業界の仲間入りを果たしたらしい。

2014-07-04

2014-05-pre-Rapperswil mailingのレビュー: N4000-N4009

さて、さくさくC++WG論文を解説していく。

[記念すべきキリ番がPDF] N4000: Towards a Transaction-safe C++ Standard Library: std::list

STLコンテナーをトランザクションセーフにするための研究の一環として、std::listをトランザクションセーフに書き直してみた実験の報告。STLコンテナー自体をトランザクションセーフにすることで、ユーザーが明示的にトランザクショナルメモリーのコードを書かなくてもすむ。

実験は、現在提案されているTransactinal Memoryを実験的に実装したGCC 4.9とそのstd::listの実装に対して行われた。

論文によると、十分に実装可能であり、変更は最小限ですんだという。変更の大半は、メモリ確保と解法、swap関数にtransaction_safeキーワードを使うだけだという。

論文では、実装経験の結果持ち上がった問題についても論じている。

size()が定数時間

C++11では、すべてのコンテナーのsize()のオーダーは低数時間であると定められた。これは、std::listをトランザクショナルセーフにする際に、scalableではなくなるという問題を引き起こす。ライブラリ拡張WGのメンバーは、C++11で軽々しくsize()を低数時間にしたのは誤りであったと認めた。議論の結果、この問題に対処するためにsize()のcomplexityを再び変更するなどということは行わないことで合意したそうだ。

size()がconst noexcept

トランザクショナルメモリーは、ロールバックを認めている。ロールバックを行うには、副作用を一時的に保持しておくストレージを確保する必要がある。ストレージを確保しようとして、確保できない場合が発生すると、bad_allocがthrowされるが、それはconst noexceptであるsize()の中で起こる。しかし、const noexceptな関数の中からそれはできない。これに対処するためには、もっと安全な方法で実装を余儀なくされる。

議論の結果、実装に内部的な静的ストレージをロックやトランザクションで保護できる自由を与えればよかろうという方向に向かったようだ。

非安全な処理を行う要素型への対応

std::listの要素型が、コンストラクターや代入の歳に、ロールバックできない副作用(I/Oなど)を引き起こす場合、いったいどうすればいいのか。

議論と経験の結果、実装はそのような非安全な要素型のインスタンス化を阻害すべきではないが、トランザクションのなかでそのようなメンバー関数を呼び出すことを、コンパイラーは禁止すべきであるという。

論文では、GCCでは、多少の変更でこの挙動を実現可能であるとしている。

論文では、この後、std::listに施した具体的な変更内容の説明が続いている。実験的実装をしたstd::listは、以下のGitHubレポジトリにおいてある。

mfs409/tm_stl

[テキストのみのPDFにする理由が一切感じられないPDF] N4001: SG5: Transactional Memory (TM) Meeting Minutes 2014/02/03-2014/05/19

トランザクショナルメモリーに関する会議の議事録

[PDFも消毒だ] N4002: Cleaning-up noexcept in the Library

標準ライブラリにnoexceptを着ける基準を見直す提案。

File System TS Active Issues List (Revision R1)
File System TS Closed Issues List (Revision R1)
File System TS Defect Report List (Revision R1)

Filesystem TSに持ち上がっている問題、解決済みの問題、議論の結果問題ではなかったと判断された既存の問題のリスト。

N4006: An improved std::{unordered_,}map::emplace

std::mapとstd::unordered_mapのemplaceにムーブ可能な値を渡すと、実際にムーブされるかどうかは、未規定である。


std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

std::unique_ptr<Foo> p(new Foo);
auto res = m.emplace("foo", std::move(p));

上記のコードを実行した結果、pがムーブされるかどうか、つまりassertに引っかかるかどうかは、規格上、未規定である。emplaceはひょっとしたらpをムーブせずにコピーするかもしれない。

emplace自体を修正するのは難しいので、挙動を保証した、emplace_stableとemplace_or_updateを新たに追加しようという提案をしたのが、N3873だ。

Issaquah会議で議論した結果、emplaceは動くべき(Just Work)だという意見が大勢を占めたので、この提案では、従来ひとつだったemplaceを三つに分割する。

N4007: Delimited iterators (Rev. 2)

ostream_iteraterの改造版、ostream_jointerの提案。

ostream_iteraterは、以下のように使いたくなる。


std::vector<int> v = { 1, 2, 3 } ;
std::cout << "(" ;
std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, ", " ) ) ;
std::cout << ")"

なるほど、これは汎用的なアルゴリズムを適用できて便利だ。しかし、この出力は、以下のようになる。

(1, 2, 3, )

実は、ostream_iteraterのデリミターは、実はデリミターではなくて、サフィックスとでもいうべき動きをするのだ。

そこで、本当にデリミターとして働くostreamのイテレーターラッパーが提案されている。ostream_jointerだ。ostream_jointerを作るためのmake_ostream_jointerもあって、以下のように使う。


std::copy( v,begin(), v.end(), std::make_ostream_jointer( std::cout, ", " ) ) ;

これを実行すると、出力は、(1, 2, 3)となる。

なお、この論文筆者は、学生に課題としてこれの実装を毎年課しているという。

[PDFは同時に粉砕されるべき] N4008: SIMD polymorphism

コンパイル時に最適なSIMD関数を型システムによって選ぶ、SIMDポリモーフィズムの提案。

ある関数があって、その関数に対して、特定の条件に対しては効率的なSIMD関数を生成できるとする。条件というのは、例えば、ループの中で、関数の引数が、固定、線形に変化、不定といった条件だ。これらの条件に対して、最適なSIMD関数を生成する。

論文は、OpenMPなどの既存のSIMD用の実装による経験を元に書かれている。論文では、上記のような条件を記述するための、何らかの文法があるものと仮定して話を進めている。

さて、あるひとつの関数に対して、条件ごとに最適な複数のSIMD関数コードと、安全にフォールバックするための通常関数コードを生成したとする。この複数の関数から、どのようにして、特定の条件に会う最適な関数を選べばいいのだろうか。

コンパイル時条件分岐というと、まずまっさきに思い浮かぶのが、テンプレート実体化とオーバーロード解決だ。残念ながら、この二つのコンパイル時条件分岐は、あまりにも選択が早すぎる。最適なSIMD関数を選ぶための条件は、テンプレート実体化やオーバーロード解決が終わった後、コンパイラーによるデータフロー解析の結果、判明する。したがって、条件が判明した時には、すでに選択が行われてしまっている。

論文では、この選択には、型システムを使うべきだと主張している。関数の集合を、ひとつの型として認識する。もちろん、関数へのポインターも、通常の関数ポインターとは異なる型で、しかもひとつの型として認識する。その実態は、複数の関数が、条件に従って適切に選ばれるのだ。実装は複数の関数の中から、適切なSIMD関数にディスパッチする。適切なSIMD関数を選択するのは、ループの外で行われるので、virtual関数呼び出しのようなパフォーマンスの問題はない。

ひとつの関数から生成される複数のSIMD関数と通常関数のコードは、ユーザーからは完全に一つの型、SIMDポリモーフィズムな型としてみえる。ユーザーが特定のひとつのSIMD関数を個別に参照することはできない(特定の条件で呼び出せば、間接的に選択可能ではあるが)

論文では、通常の関数へのポインターとSIMDポリモーフィズムな関数へのポインターを、相互に型変換できるべきであるとしている。また、相互に等価を比較できるべきであるとしているが、等価比較には、色々とコストがかかり、最適な実装方法がないとしている。

また、複数のアーキテクチャが混在するヘテロコンピューター環境が珍しくない現代、このSIMDポリモーフィズムの機構を使って、実行時に最適なコードを選ぶといった将来性もあるであろうが、この論文では、今回はそれを考察しないと結んでいる。

ただでさえわかりにくい型シムテムを、さらにわかりにくくする提案だ。そして、まだ具体的なSIMD条件を記述するための文法が提案されていない以上、この論文だけではどうしようもない。

N4009: Uniform Container Erasure

コンテナーから条件を満たした要素をすべて消し去り、サイズも変えるerase_if(container, pred)の提案。

以下のように使う。


std::vector<int> v = { 1231, 132, 2321 , 222, 35, 6643, 11, 2, 890, 33} ;

std::erase_if( v, [](auto && elem ){ return elem < 100 } ) ;

// vは{1231, 132, 2321, 222, 6643, 890}

従来、これをするには、以下のように書く必要があった。


v.erase(
    std::remove_if(v.begin(), v.end(),
        [](auto && elem ){ return elem > 100 }
    )
    , v.end()
    ) ;

しかし、もし以下のように書いてしまった場合、意図通りには動かない上に、コンパイルが取ってしまい、実行できてしまう。


v.erase(
    std::remove_if(v.begin(), v.end(),
        [](auto && elem ){ return elem > 100 }
    ) ) ;

これは、STLコンテナーのeraseメンバー関数には、イテレーターをひとつだけ取るオーバーロードと、イテレーターの範囲を取るオーバーロードがあるからだ。コンパイラーはこのミスを警告すらできない。

このため、erase_ifを提案する。

なぜerase_ifはメンバー関数ではないのか。このようなコンテナーごとに最適な実装が異なるアルゴリズムは、従来ならばメンバー関数として実装していたではないか。この理由としては、basic_stringがやりすぎてカオスなことになってしまっているのを反省してのことらしい。

また、名前がややこしいという問題もある。eraseとremoveは意味が似通っていてわかりにくい。論文ではこの疑問に対して、eraseというのは、listとforward_listのような例外を除けば、コンテナーのサイズを変更する場合に一貫して使われている。コンテナーのサイズを変更するremoveはない。また、eraseという非メンバー関数は使われていないとしている。

ただし、やはりわかりにくいとは思う。バイク小屋議論は尽きないものだ。

なぜpredicateだけなのか。なぜ削除すべき値を指定するオーバーロードはないのか。問題は、連想コンテナーとunordered連想コンテナーには、erase(key)というメンバー関数があり、混同しやすいからだとしている。

ドワンゴ広告

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

この記事を執筆中に、社内の筆者の近所の席から、何やらダースベイダーの呼吸音のような音が聞こえると思ったら、ビーダマン後期の製品、コバルトブラスタードライブキャノンとデストロイドラゴンで遊ぶエンジニアがいた。リモコンで前身と旋回操縦可能な上に、ビー玉単発や連写までできるすぐれものだ。ただし、シメ撃ちはできそうにない。シメ撃ちできないと滝をぶち破ったりできないと思うのだが、いったいどうするのだろうか。

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

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

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

Ubuntu 14.04のUnityの設定をぶっ壊した場合の修復方法

今朝、コンピューターを起動して、Ubuntu 14.04にログインしようとしたら、なぜか画面が固まってしまった。

まあ、この程度は情報強者たる筆者にとっては、造作もないことだ。Ctrl+Alt+F1で華麗に仮想コンソールに切り替えて、Upstartのinitctlを使ってlightdmを再起動させた。

$sudo restart lightdm

カチャカチャ・・・ターンッ!

restartは、initctl restartの代わりに使えるinitctlへのシンボリックリンクだ。おそらく、Ubuntuも将来的にはsystemdに移行するであろうから、いずれはsystemctlを使う必要があるであろう。だが、それはまだ先の話だ。

Ctrl+Alt+F7で戻ったところ、無事にlightdmによるログイン画面が表示された。さっそくログインしなおしたが・・・Unityがぶっ壊れていた。

背景とマウスポインターは表示される。右クリックするとメニューも表示される。しかし、それ以外のUIが一切ない。ランチャーもメニューバーもないので、このままではGUI作業ができない。GNOMEターミナルを開くキーボード・ショートカットも動かない。

仕方がないので、情報弱者らしく再起動をしてみたが、

$sudo shutdown -r now

Unityは壊れたままだった。

やってしまった。これはおそらく、無理やりlightdmを再起動させたので、どこかの設定ファイルが壊れてしまったのだろう。試しに別のユーザーでログインしてみると、ランチャーもメニューバーも通常通り表示される。しかし、Unityの設定ファイルをぶっ壊してしまったので別ユーザーを使います、というのは情報弱者にもほどがある。さて、どうやって復旧しようか。

あるいは、この機会に、別のWMを試してみるという手もある。しかし、何はともかく、Unityを復旧させたい。

まず、Compizの設定をリセットしようと思い立った。Compizの設定をリセットするには、CompizConfig Settings ManagerというGUIのソフトウェアを使う必要がある。しかし、ランチャーもターミナルもないと、起動することができない。

調べたところ、DISPLAY変数を適切に設定することで、仮想コンソールからプログラムを起動してそのウインドウを望みのディスプレイに表示できるようだ。

$sudo apt-get install compizconfig-settings-manager
$export DISPLAY=:0
$ccsm

無事に起動できたので、Unityプラグインを設定しなおしたり、デフォルトの設定を読み込ませたりしてみたが、残念ながら、これでは直らなかった。さて、どうするか。

さらに調べたところ、unityを起動するラッパーである/usr/bin/unityに、--resetオプションを指定すると、設定ファイルをリセットしてくれるという。

$man unity
unity(1)                              Linux User's Manual                              unity(1)

NAME
       unity - wrapper for starting the unity shell and handling fallback

SYNOPSIS
       unity [options]

DESCRIPTION
       The  unity program can be used to start the Unity shell as a compiz module, and to spec‐
       ify how to handle logging, debugging, as well as how to deal with the user's profile.

OPTIONS
       --advanced-debug
              Runs unity under debugging (using GDB or another debugger tool) to help  tracking
              issues. Should only be used on request from a developper following a bug report.

       --log filename
              This  parameter,  followed  by a path or filename, tells the Unity shell to store
              logs in the specified file.

       --reset
              This option allows the user to reset profile parameters in compiz and restart the
              Unity shell with default settings.

       --verbose
              This  option turns on displaying additional debugging output for the Unity shell.
              It can be used by the user to debug configuration issues. This  option  is  often
              used along with the --log option to save output to a file.

SEE ALSO
       unity-panel-service (1)

                                        9 December 2010                                unity(1)

なるほど、ではさっそく

$ unity --reset
ERROR: the reset option is now deprecated

なんだと。

さらに調べたところ、Ubuntu 14.04では、unity-tweak-toolが公式なレポジトリに入っていて、これにはUnityの設定をリセットする機能があるようだ。

$sudo apt-get install unity-tweak-tool
$man unity-tweak-tool

unity-tweak-tool(1)                   Unity User's Manual                   unity-tweak-tool(1)

NAME
       unity-tweak-tool - configuration manager for Unity desktop environment

SYNOPSIS
       unity-tweak-tool [options]

DESCRIPTION
       The unity-tweak-tool program can be used to tweak Unity desktop environment. Unity Tweak
       Tool is a one-stop settings manager for Ubuntu Unity.

OPTIONS
       -u     Starts unity-tweak-tool in Unity section.

       -w     Starts unity-tweak-tool in Window Manager section.

       -a     Starts unity-tweak-tool in Appearance section.

       -s     Starts unity-tweak-tool in System section.

       --reset-unity
              Reset Unity, wiping all changes to configuration.

BUGS
       Please report any bug you may experience to the unity-tweak-tool developers, who can  be
       reached at https://launchpad.net/unity-tweak-tool.

AUTHOR
       unity-tweak-tool was written by Freyja Development Team and this manual page by Barneed‐
       har Vigneshwar <barneedhar@ubuntu.com>.

       Both are released under the GNU General Public License, version 3 or later.

                                        11 February 2013                    unity-tweak-tool(1)

これを使ってみよう。

$unity-tweak-tool --reset-unity

これはうまくいった。無事に、Unityが復旧した。

たまに環境が壊れると、刺激があって面白い。動かないものを動くように直す作業は楽しい。しかし、それは危険な誘惑である。

xkcd: Cautionary

Linux: 実際にあった話:第一週

もしもし、あたしあたし、姪だけど。新しいパソコン手に入れたんだけどさ、Windowsとか入れたくないのよ。Linuxとかいうやつのインストール手伝ってくれない?

いいよ

第二週

XORGが壊れたって。XORGって何? どうすればいいの
「manページ教えるよ」

第六週

autoconfigがうまくいかないんでUbuntuからDebianに変えることにする
「えっ」
Gentooにするかも
「やばい」

第十二週

「最近電話に出ないけど」

寝らんない。カーネル、コンパイル、しなきゃ。

「手遅れか」

親に告ぐ:誰か他人に教わる前に、子供にLinuxを教えるべきである。

ドワンゴ広告

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

昨日、いつも通り午後2時頃にドワンゴに出社したところ、ACアダプターを家に忘れたことに気がついたので、その日はバッテリーが切れる前にさっさと退社した。今日は朝からネタができたので、午前11時に出社した。

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

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

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

2014-07-02

妖怪ハンモック

さて、妖怪ハウスにハンモックを導入してしばらくたった。筆者がハンモックを購入した理由は他でもない。夜にハンモックで寝るためである。ハンモックで寝るということには、ロマンがある。

最初に買った、ハンモックを吊るす土台付きのハンモックは、寝っ転がってリラックスするにはよいが、寝具として使うには機能不足であった。そこで、もっと幅が広いハンモックをもう一枚購入した。問題は、二枚目のハンモックは多きすぎて、すでに買った土台には取り付けられない。ベランダの手すりに取り付けることはできるのだが、日光が直接顔面にあたって寝られない。

この問題を解決するために、筆者はビーチパラソルを購入した。幸い、アマゾンには安いビーチパラソルが売られていた。これでハンモックでも快適に寝られるはずである。さっそく、今夜は雨が振らない天気予報であることを幸い、寝心地を試してみようと思う。

ビーチパラソルは、ハンモックの他にも色々と役に立つはずである。

日々変わりない平凡な日常では腐ってしまう。常に変化が必要である。次はどんな変化を試みようか。

2014-07-01

2014-05-pre-Rapperswil mailingのレビュー: N3990-N3999

C++WG論文がたまっているので消化していきたい。

[出だしからPDF] N3990: Adding Standard Circular Shift operators for computer integers

サーキュラーシフト演算子(Circular shift operators)、つまりローテート演算子の提案。

サーキュラーシフト演算子とは、シフト演算子に似ているが、あふれでたビット列が、反対側に現れる。つまり、11110000という8bitの整数を左に2、サーキュラーシフトすると、11000011となる。

ローテート操作は、暗号計算などの分野で多用されているため、高速である必要がある。多くのアーキテクチャでは、ローテート操作をするプロセッサーネイティブの命令が存在する。しかし、C言語では、ローテート操作のための標準的な方法が存在しなかった。そのため、標準C++の枠内で移植性のある実装をするには、既存のシフト演算子を使わなければならない。

GCC 4.7以降では、そのようなシフト演算子を組み合わせたローテート操作を認識し、ローテート命令のあるターゲット向けならば最適化できる。しかし、単にコードを読み書きする都合からも、標準の方法が存在すべきである。

提案されている演算子は、<<<. >>>, <<<=, >>>=の4つである。意味は明らかだろう。この演算子は、もちろんオーバーロード可能だ。

サーキュラーシフト演算子の左辺は、符号なし整数でなければならない。もし、符号付き整数が指定された場合の挙動は未定義である。

void f( int x )
{
    // 挙動は未定義
    x <<< 1 ;
}

サーキュラーシフト演算子の右辺は、正の整数で左辺の整数型のビット数未満でなければならない。右辺が負数であったり、左辺の整数型のビット数以上であった場合の挙動は、未定義である。

// 1バイトは8bitであるとする
void f( unsigned int x )
{
    // 挙動は未定義
    x <<< -1 ; 

    // 挙動は未定義
    x <<< sizeof(x) * 8 ;
    x <<< sizeof(x) * 8 + 1 ;
}

挙動は未定義であって、ill-formedであるとは定められていない。もちろん、未定義であるからして、ill-formedとなっても規格準拠の実装である。ゼロ除算と同じような扱いだ。

[またPDF] N3991: Task Region R2

fork-joinという考え方の並列実行のための高級ライブラリ、Task Regionの提案。前回の論文、N3832からの変更点としては、task_regionから発生した子タスクと明示的に通信するためのtask_region_handle。

N3992: Agenda and Meeting Notice for WG21 Telecon Meeting

6月6日に開催された電話会議の予定表

[まだPDFだ] N3993: On Parallel Invocations of Functions in Parallelism TS

現在TSに提案されている、<algorithm>に実行ポリシーによるタグディスパッチを追加して、並列実行やベクトル実行が出来るようにしようという提案の文面案で、ソートはswapを並列に呼び出すが、要素がオーバーラップしない時だけに限るという保証を与えるために、Hans Boehmが文面案を改正すべきだという意見を出したので、それに伴い、文面案を変更する提案論文。

N3994: Range-Based For-Loops: The Next Generation (Revision 1)

range-based for loopで、for ( elem : range ) を、for ( auto && elem : range )にするための軽いシンタックスシュガーの提案。

N3995: A proposal to add shared_mutex (untimed) (Revision 2)

C++11でshared_mutexと呼ばれていたものは、TimeLockable要件(try_lock_for/try_lock_until)を満たすので、実はshared_time_mutexと呼ぶべきであったので、そのように改名する提案が可決された。そこで、TimeLocakble要件を満たさない、本当のshared_mutexを追加する提案。

[長大なPDF] N3996: Static reflection

130ページもある長大なPDFの論文。

静的リフレクションに関する論文。

例えば、クラスの内部状態をバイナリとかXMLとかJSONなどといった何らかのフォーマットに書き出したり、そのフォーマットから読み込んでクラスの内部状態を再現したりしたいとする。これは一般に、Serializationと呼ばれている。serializationを実装するには、クラスの意味のあるデータメンバーをそれぞれ読み書きする必要がある。これを手動であらゆるクラスに対して手で書くのは面倒である。極めて単調で、機会的に生成できるコードである。何か、クラスのデータメンバーをコンパイル時に列挙して、それを元にコンパイル時にコードを生成するような機能があればいいのだが。

その機能を提供するのが、リフレクション(Reflection)だ。リフレクションによるリフレクティブプログラミング、これはメタプログラミングの一種である。そのリフレクションをコンパイル時に行うので、静的リフレクションとなる。

論文は、静的リフレクションで取得可能なコード情報や、Technical Specification文面案など、やたらと大量の文章を含むので、ここまで膨れ上がった。

[PDFから身を守りたい] N3997: Centralized Defensive-Programming Support for Narrow Contracts (Revision 5)

防衛的プログラミングと称して、高機能assertマクロをライブラリとして追加する提案。

筆者はCプリプロセッサーを使う提案に反対の立場である。

N3998: C++ Latches and Barriers

ラッチとバリアーというライブラリの提案。

ラッチというのは、ひとつ以上のスレッドをブロックしておくためのライブラリである。ラッチは初期化時にカウントを指定する。latch::arrive()を呼び出すことで、カウンターがデクリメントされる。カウンターがゼロに達すると、latch::wait()を呼び出すことでブロックされていたスレッドが実行を再開する。


// ラッチオブジェクト
// カウンターは3
std::latch l( 3 ) ;


// (複数の)スレッド
void waiting_thread()
{
    // 処理がすべて終わるまで待機
    l.wait() ;
}

// 処理、三回呼ばれたらラッチによるブロックが解除される。
void operation()
{
    l.arrive() ;
}

ラッチは、一度きりしか使えず、再利用できない。

バリアーは、再利用できるラッチである。

さらに、notifying_barrierというクラスもあり、これは、終了条件に達した時点で、設定した関数が呼ばれるものである。

それにしても、どうも名前が聞きなれなくてややこしいと思うのは筆者だけだろうか。とくに、スレッド間の同期でいえば、ずぼらな人のためのアトミック操作であるメモリバリアーとややこしいと思うのだが。

[またPDF] N3999: Standard Wording for Transactional Memory Support for C++

トランザクショナルメモリーの文面案。前回からの変更は小粒。

ドワンゴ広告

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

今日、社内で謎のダンスが流行っていた。

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

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

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

2014-06-30

Old New Thing: 未定義動作はタイムトラベルを引き起こす(他にもいろいろあるけど、タイムトラベルが一番ぶっ飛んでる)

Undefined behavior can result in time travel (among other things, but time travel is the funkiest) - The Old New Thing - Site Home - MSDN Blogs

久しぶりに紹介するRaymond Chenのブログ記事。

C言語とC++では、様々な部分が、ドラゴンの住まう地というレッテルを貼られている。いや、正式には、未定義動作とされている。

未定義動作が発動した場合、何でもありだ。例えば、変数は同時にtrueでもfalseでもありえる。John Regehrは興味深い例のリストをまとめて、未定義動作コンテストの受賞者もある。

以下の関数を考える。

int table[4];
bool exists_in_table(int v)
{
    for (int i = 0; i <= 4; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

これがタイムトラベルと何の関係があるんだ、と読者は疑問に思うであろう。ちょっと待て、あわてんぼうさん。

まず、ループの処理に間違いがあることに気がつくはずだ。結果として、関数はループを終了する前に、table配列の最後の一つ後ろを読んでしまう。古典的なコンパイラーは、特にこれを気にしない。単に、(それが言語のルールに違反するものであるにも関わらず)配列の要素の範囲を超えた領域を読むコードを生成するだけだし、配列の最後の一つ後の要素が条件にあうならばtrueを返す。

一方、古典的ではないコンパイラーは、以下のような解析を行うかもしれない。

  • ループの最初の4回の実行で、関数はtrueを返すかもしれない
  • iが4のとき、コードは未定義動作を行う。未定義動作は何をしてもよいので、我輩としてはそんなの無視して、iは決して4にはならないものとして話を進める。(もし、この仮定が破られた場合、何か予期せぬことが起こるであろうが、まあ、そんなことはどうでもよい。未定義動作は、我輩にとっては何をしてもいいことなのだからな)
  • iが5の場合は、決して発生しない。なぜならば、iが5に到達するには、iはまず、4に到達しなければならない。吾輩は、すでにiが4には到達しないと看過しておるからだ。
  • 故に、すべての合法なコードパスはtrueを返すものである。

この結果、非古典的コンパイラーは、関数を以下のように最適化できる。

bool exists_in_table(int v)
{
    return true;
}

やれやれ、こいつはちっと変だな。関数は未定義動作によって最適化されたため、何もしなくなってしまった。たとえ値がtableに存在しなくても(アクセスするのが違法な5番目の要素にすらなくても)、関数はtrueを返すのだ。

さて、この非古典的挙動をもっと推し進めてみよう。コンパイラーは、未定義動作は決して起こらぬものと看過できる(なぜならば、もし起こった場合、コンパイラーは何でもすることが許されている)のであるから、コンパイラーは未定義動作を最適化の助けとできる。

int value_or_fallback(int *p) { return p ? *p : 42; }

上記の関数は、int型へのポインターを取り、ポイントしている値か、(もしポインターがnullの場合は)、フォールバック値である42を返す。ここまではいい。

さて、この関数にデバッグ用のコードを挿入してみよう。

int value_or_fallback(int *p)
{
 printf("The value of *p is %d\n", *p);
 return p ? *p : 42;
}

この新しい行には、バグがある。ポインターpをnullであるかどうか確認せずにデリファレンスしているのだ。この些細なバグは、様々な結果を引き起こす。非古典的なコンパイラーは、この関数を以下のように最適化する。

int value_or_fallback(int *p)
{
 printf("The value of *p is %d\n", *p);
 return *p;
}

なぜならば、コンパイラーは、nullポインターチェックは必要ないと看過するからだ。もし、ポインターがnullであれば、どうせprintfは未定義動作を引き起こすのであるからして、コンパイラーはポインターがnullの場合は、何でもすることが出来るのだ(これにはポインターがnull出ないがごとく振る舞うことも含まれる)

さて、これまだまだ驚くに当たらない。読者の中には、コンパイラーの最適化としてむしろ期待している仁もいるだろう(例えば、もし三項演算子がマクロの中に隠されていた場合、それがおそらくはfalseの場合、コンパイラーに除去して欲しいと思うだろう)

しかし、非古典的なコンパイラーは、このバグ関数を利用して、タイムトラベルを始めるのだ。

void unwitting(bool door_is_open)
{
 if (door_is_open) {
  walk_on_in();
 } else {
  ring_bell();

  // wait for the door to open using the fallback value
  fallback = value_or_fallback(nullptr);
  wait_for_door_to_open(fallback);
 }
}

非古典的なコンパイラーは、この関数全体を、以下のように最適化できる。

void unwitting(bool door_is_open)
{
 walk_on_in();
}

ハァ?

value_or_fallback(nullptr)という呼び出しは、すべてのコードパスで未定義動作を引き起こすとコンパイラーは認識する。この解析を前方に持ってくると、door_is_openがfalseであった場合、else分岐はすべてのコードパスで未定義動作であると認識する。つまり、else分岐全体が、到達不可能である。[2]

さて、タイムトラベルの時間だ。


void keep_checking_door()
{
 for (;;) {
  printf("Is the door open? ");
  fflush(stdout);
  char response;
  if (scanf("%c", &response) != 1) return;
  bool door_is_open = response == 'Y';
  unwitting(door_is_open);
 }
}

非古典的なコンパイラーは、解析結果を持ってきて、「もし、door_is_openがfalseであれば、挙動は未定義である」とし、函数を以下のように書き換えるかもしれない。

void keep_checking_door()
{
 for (;;) {
  printf("Is the door open? ");
  fflush(stdout);
  char response;
  if (scanf("%c", &response) != 1) return;
  bool door_is_open = response == 'Y';
  if (!door_is_open) abort();
  walk_on_in();
 }
}

これをみると、オリジナルのコードは、クラッシュする前にドアベルを鳴らすが、書き換えられた関数は、ベルを鳴らすのをスキップして即座にクラッシュする。これは、コンパイラーは過去に戻ってベルを鳴らさないようにしたともとれる。

この、「過去にさかのぼる」というのは、ファイルのような外部にみえるオブジェクトでも起こりうる。なぜならば、標準規格は未定義動作を引き起こした時、何でもありなことを認めているからだ。その何でもありというのは、タイムマシンに飛び乗って、fwriteを呼び出さなかったかのように振る舞うことも含まれる。

コンパイラーはタイムトラベルを引き起こすなど許されないと主張したとしても[1]、先行する処理がなかったことにされることはある。例えば、未定義の操作により、ファイルバッファーが破壊され、データは実際に書き込まれないということが起こりうる。たとえ、バッファーがフラッシュされたとしても、未定義の操作はftruncateを呼び出して、論理的に書き込んだデータを除去することがありうる。あるいは、作ったはずのファイルにDeleteFileを呼び出してファイルをデリートすることもあり得る。

これらの挙動はすべて、同じ観測効果を持つ。特に、先行する処理が発生しなかったようにみえる。それが実際に起きてなかったことにされたのか、最初から起こらなかったのかは、コンパイラー理論の上からは、どうでもいいことである。

コンパイラーは未定義処理の結果を時間をさかのぼって適用することもできるということだ。

[1] 標準規格は、明示的に未定義動作によるタイムトラベルを認めている。

しかし、もしそのような実行が未定義の操作を含む場合、この国際標準規格は実装に対し、そのような入力に対し、いかなる実行上の制約をも課すことはない(未定義操作に先行する操作をも含む)

[2] この変換を考える別の視点としては、コンパイラーはelse分岐はすべてのコードパスで未定義の挙動を引き起こすので、コードを以下のように書き換えるとみることもできる。

void unwitting(bool door_is_open)
{
 if (door_is_open) {
  walk_on_in();
 } else {
  walk_on_in();
 }
}

未定義動作では何が起こっても許されるというということを利用した例だ。この例では、「walk_on_inを間違って呼ぶ」という何かになる。

ボーナス小ネタ:未定義動作には、一見すると明らかではない場合もある。例えば、nullポインターをデリファレンスするのは、何か危険なことをする前にデリファレンスの対策をしたとしても、依然として未定義動作になる。

int *p = nullptr;
int& i = *p;
foo(&i); // undefined

&と*は、お互いに打ち消しあい、あたかもfoo(p)と書いたかのようになると考えるかもしれないが、存在しないオブジェクトへのリファレンスを作った時点で、使わなくても、未定義動作を引き起こすのだ(§8.5.3(1))

参考文献:なぜすべてのCプログラマーは未定義動作について知らねばならないのか。Part 1, Part 2, Part 3

ドワンゴ広告

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

ところで、6月28日に土曜日に開催したドワンゴC++勉強会#1は、あまりにも本物のC++プログラマーを呼んでしまった。本物のプログラマーは怠惰を美徳とするものである。また、本当に必要になるまで行動しないものである。そのため、二人とも、勉強会の前日、当日にスライド資料を作成するという、エクストリーム資料作成を敢行していた。

また、にわかにでっち上げたドワンゴC++勉強会#1は、どうやら出勤扱いになるらしく、筆者には振替休日が与えられた。振替休日となるべき日は筆者が自由に設定できるので、もちろん、図々しくも今度の月曜日に設定して申請しておいた。

今後も勉強会は積極的に開催していきたい。

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

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

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

新たなC++世代

先日のドワンゴC++勉強会で、筆者は若いC++世代と話をする機会を得た。若いとはいえ、筆者よりせいぜい5,6年歳が離れているだけで、C++を学び始めた歳も、筆者より5,6年遅かったので、都合10年ほど、筆者より後にC++を学び始めたというだけの話だ。しかし、C++にとって、いやプログラミング全般にとって、10年はあまりにも長過ぎる。

筆者がC++を書物で学び始めた頃、まだテンプレートはまともに実装されていなかった。筆者がコンピューターを所有し、C++を実際にコンパイル出来るようになった時、ようやく主要なコンパイラーがC++を実装し始めていた。当時最新のテンプレート事情を解説した、C++ TemplatesやC++ Template Metaprogrammingを、筆者は読んでいた。C++ Templatesは、10年後の2013年に日本語に翻訳された。当時最新だった内容は、今となっては歴史的資料でしかない。

そう、筆者の次の世代は、C++を学び始めた時からautoがあり、decltypeがあり、Variadic Templatesがあるのだ。当時、我々が必死に技巧を弄してエミュレートしていた機能が、ネイティブに存在するのだ。

ああ、もう新しい世代の時代なのだ。

ところで、ドワンゴC++勉強会では、CFrontを当時現役で使っていたという世代の人にもあった。筆者は、CFrontは文献でしか知っていなかったので、驚いてしまった。しかも、まだテンプレートが実装される前のCFrontを使っていたらしい。もっと話を聞きたかったものだ。

ドワンゴ広告

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

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

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

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

2014-06-29

ドワンゴC++勉強会#1を開催した

去る6月28日に、歌舞伎座タワーのドワンゴのセミナールームで、ドワンゴC++勉強会 #1を開催した。

今回は、でちまるさん(実際かわいい) (decimalbloat)と、狂える中3女子ボレロ村上/陶芸C++er (bolero_MURAKAMI)を発表者として招いて、最強の勉強会を行った。

ボレロ村上は、コンパイル時メタプログラミングで、レイトレーシングや波形生成などを行っている。本職は岡山の陶芸家である。

この日の発表は、テンプレートの再帰深度を下げる話や、コンパイル時レイトレーシング、波形生成、またC++の標準ライブラリのうち、constexprに対応できるものがまだまだあるという話であった。

でちまるさんは、Cプリプロセッサーでメタプログラミングを行っている。本職は艦これプレイと艦これ関連のコンテンツ収集である。

この日の発表は、いかにして数値というものを解しないCプリプロセッサーで四則演算を行うかとか、再帰もないのに現実的な回数のループを実現するかという、Cプリプロセッサーメタプログラミングにおける基本的な考え方から発表した。結局は、すべてをマクロ名の結合と置換で強引に行ってしまえばいいのだ。

Cプリプロセサーメタプログラミングに使われている極めて強引な手法を、彼はかの有名なニンジャスレイヤーのレッドゴリラ=サンの名言、「何事も暴力で解決するのが一番だ」を引いて説明した。言語というものは、以下に制限を加えようとも、必ず乱用されるものである。

なお、でちまるさんは今回のCプリプロセッサーメタプログラミング発表のまとめとして、「PHPを使え」というありがたい結論を提示した。

今回は、C++界で異彩を放つ強力な二人の発表者を呼んだので、発表内容は極めて濃くなった。二人の発表内容は、いったい何の役に立つのかと思った人もいるかもしれぬ。しかし、これらの技法は、C++の新機能を設計する上で、非常に参考になっているのだ。

筆者は、C++の歴史と題して、C++が作られた経緯や、最近の日本のC++標準化委員会の事情を説明した。

C++の歴史スライド資料

さて、LT発表は5人。

最初の発表者、南山まさかず@東京 (minamiyama1994)君は、テンプレートと依存型(C++の規格用語の依存型ではない)として扱う方法について発表していた。残念ながら、筆者には理解できない世界の話であった。

次の発表者、抹茶ココア (fimbul11)さんは、C++14にライブラリとしても追加されたinteger sequenceの技法や、テンプレートの再帰深度を線形増加より押さえる技法について発表した。

ぽんこつ@MyFleetGirls開発中 (ponkotuy)さんは、いかにCocos2dxがC++的ではないかということについて発表した。発表を聞く限り、Cocos2dxはクソであるという認識を得た。

かるぱねるら (karupanerura)さんの発表は、なぜか記憶に残っていない。たしかCocos2dxについてクソであると言っていた気がするが、はて。

ψ(プサイ) (tikal)ちゃんは、かわいい狐のコスプレをしていた。なんでも、いなり、こんこん、恋いろは。に出てくる、コンというキャラクターであるようだ。コンちゃんはvalgrindという、実行時メモリチェッカーについて発表した。Cocos2dxは非常にクソであると言っていた。また、AMDやnVidiaの不自由なドライバーの中のクソコードがよくvalgrindのチェックに引っかかったりしてムカつくということも言っていた。

ドワンゴC++勉強会は、ドワンゴらしく、ニコ生による配信も行った。

ドワンゴC++勉強会 #1 - 2014/06/28 14:00開始 - ニコニコ生放送

問題は、当日使っていたケーブルに不備があったので、急遽ドワンゴ社員が買いに走るなどという障害に見舞われたそうだ。

今回、connpassにて参加者を募集したところ、90人枠が一日と立たずに埋まってしまった。どうやら、C++勉強会には相当の需要があるようだ。今回、参加できなかった人達のためにも、これからも頻繁に開催していきたい。

筆者がドワンゴに入社してから、セミナールームを使って勉強会を積極的に開いてほしいとは言われていたものの、他の社員への負担などを考えて、今まで勉強会を開くことはなかった。今回、勉強会を開いてみたところ、予想以上の応募数があったので、これからは積極的に勉強会を開催したい。

今回の勉強会は、だいぶ重い内容であったので、次の勉強会は、バランスを取るために軽くしたい。そもそも、勉強会は自分で発表してこそ勉強になるので、次回の勉強会は、一般の発表者を多く募集したいところだ。とにかくC++WG論文を早く読まねばならない。

ドワンゴ広告

この記事はドワンゴ勤務外に書かれた。この勉強会がドワンゴ勤務に当たるのかどうかまだ分からない。仕事であるとすれば、休日出勤となるので、振替休日がもらえるはずである。しかし、今は読むべきC++WG論文が大量にたまっているし、それにサボろうと思えばいくらでもサボれるので、どうでもいいことである。

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

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

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

2014-06-26

誰かから送られてきたコスプレ衣装

昨日、妖怪ハウスに筆者の宛名でアマゾンからダンボールが送られてきた。はて、これ以上何かを注文した覚えはないがと不審に思いながら開けてみると、コスプレ衣装だった。送られてきたのは、おそらくは、このアサシンクリードのコスプレ衣装だ。

コスプレ衣装とあって身構えたが、どうやら、それほど奇抜でもない青いパーカージャケットのようだ。デザインは左右非対称で、右側にチャックがついている。左胸部分にも短いチャックがついているが、これは飾りでポケットではなく、開けても裏地がみえるだけだ。

私の趣味にはあわないが、この程度のデザインならば、普段着にできる人はできるだろう。実際、妖怪ハウスの住人の一部は、欲しいと言っていた。

2014-06-25

Clangが現在実装しているC++1z機能

注意:この記事の内容はC++17の正式な規格では変わっている可能性が高い。

Clang - C++1z, C++14, C++11 and C++98 Status

C++1z、あるいはC++17と呼ばれているC++の次期メジャーアップ規格に提案中の新機能のうち、Clangがすでに実験的実装を行っているものがある。これは、コンパイラーオプションに-std=c++1zを指定することで使うことができる。実装されている機能は、いずれも、まだドラフトにすら入っていない、提案論文しかない機能である。

本記事の執筆現在、Clangの-std=c++1zで実験的実装がされている提案は以下の通り。

N3928: static_assert with no message

C++11で追加されたstatic_assertは、必ず文字列リテラルを指定しなければならない。

// エラー
static_assert( true ) ;

// OK
static_assert( true, "" ) ;

文字列リテラルを指定したくない場合でも、必ず文字列リテラルを書かなければならない。これは極めて面倒で冗長だ。

そこで、N3928提案では、文字列リテラルを取らないstatic_assertの文法を追加する。

// OK, N3928提案
static_assert( true ) ; 

N3981: Disabling trigraph expansion by default

既存の巨大なコードベースを検索したところ、トライグラフは一切意図的に使われていないことが判明した。トライグラフが使われているのは、トライグラフによる置換を防ぐためのエスケープと、コンパイラーやCプリプロセッサー実装のテストコードの中だけであった。トライグラフには現実の需要がない上、コードを書く妨げになっている。N3981では、トライグラフを取り除く提案をしている。

以下のコードを考える。


#include <iostream>

int main( )
{
    std::cout << "??=" << '\n' ;
}

このコードを実行した結果、現行規格ならば、"#"が出力され、N3981提案では、"??="が出力される。

N3994: Terse range-based for loops

rage-based for loop、for ( elem : range )を、for ( auto && elem : range )に置き換える軽いシンタックスシュガーの提案。

// N3994提案
int main()
{
    char range[] = "hello" ;

    // for ( auto && elem : range ) と同等 
    for ( elem : range )
    {
    // 処理
    }

}

なぜauto &&なのかについては、色々と理由があるので、詳しくは論文を参照。

N4051: Allow typename in a template template parameter

テンプレートテンプレートパラメーターは、文法上、classキーワードしか使えなかった。

// 現行規格
template <
    template < typename T >
    class U // ここにtypenameキーワードは使えない
>
struct X { } ;

テンプレートテンプレートパラメーターに渡せる型がクラス型しかなかった昔はともかく、今は、エイリアステンプレートがある。そこで、typenameキーワードも許可する提案。

// N4051提案
template <
    template < typename T >
    typename U // classでもtypenameでもよい
>
struct X { } ;

以上、小粒な新機能の実装が多い。これらは実装がそれほど難しくもないし、おそらくは、ドラフト入りして制式採用される機能だと思うが、最初に警告したように、まだドラフト入りすらしていない機能であるので、注意されたい。

ドワンゴ広告

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

今日、社内のくだらない雑談チャットで、ドワンゴに必要なのは社内猫であるという意見が出た。ネコアレルギーの社員との兼ね合いは難しいだろうが、猫のいる職場は、確かに生産性が下がるのですばらしい。あれ? なにか違う気がする。

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

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

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

2014-05-pre-Rapperswil mailingのレビュー: N3980-N3989

引き続き、2014-05-pre-Rapperswil mailingをレビューしていく。

N3980: Types Don't Know #

「型はハッシュのことなんざ知ったこっちゃねえんだよ」という挑発的なタイトルの論文

ある型をunorderedコンテナーに対応させるには、ハッシュ値が計算できなければならない。ユーザー提供したクラスは、ユーザーが自力でstd::hashを特殊化してハッシュ値の計算を実装しなければならない。問題は、適切なハッシュの計算というのは、極めて難しい技術であり、そんじょそこらの並のプログラマーは正しく書くことが出来ない(我は書けるなどと豪語するのはバカの証拠である)

これまで、N3333N3876で、バカでもユーザー定義型をハッシュ対応させられるようにしようという提案が出ていたが、これはどちらも、std::hashに既存の対応した型を放り込んでハッシュ値を生成するのを楽にしようというライブラリであって、汎用性に欠ける。

そこで、ハッシュアルゴリズムをテンプレートで変えられるようにし、また、演算子を定義するかのようにクラスをハッシュ計算に対応させられる新たなライブラリ、std::uhashを提案している。

「型はハッシュの事情など知らぬ」というのは、型はハッシュ値がどのように計算されるかという事情など知ったことではないし、知るべきでもないということだ。型が知っているのは、型のオブジェクトを区別化するための情報だ。ハッシュ値計算に必要な、オブジェクトが等しいか状態にあるかどうかに関わる情報を、ハッシュ値計算に混ぜ込む方だ。ハッシュ値がどのように計算されるかという内部事情を知る必要はない。

N3980では、ハッシュ計算に対応させたいクラスに、friend関数hash_appendを定義させる。そして、hash_appendをADL経由で呼び出す。

class X
{
    int i ;
    std::vector<int> v ;

public :
    template < typename HashAlgorithm >
    friend
    void
    hash_append( HashAlgorithm & h, X const & x ) noexcept
    {
        // unqualified lookupでADLを発動させ、
        // ADL経由で見つからなかった時にstd::hash_appendを発見できるようにするための
        // 小汚いテクニック
        using std::hash_append ; 

        hash_append( h, x.i, x.v ) ;
    }
} ;

このように、std::hash_appendをusing宣言で関数のブロックスコープに引っ張りこんでおいた上で、unqualified lookupでhash_appendを関数呼び出しする。すると、ADLで発見されるhash_appendと、std::hash_appendが等しくオーバーロード解決の候補となり、最適な関数が呼び出される。

クラス定義内でfriend関数定義をしているので、このhash_appendは、ADL経由でしか呼び出すことが出来ない。

実際にハッシュを計算するのは、テンプレート引数HashAlgorithmによって、ハッシュ計算に必要な情報を指示する部分から切り離している。

最終的に、ハッシュ計算はビット列をhashAlgorihmに渡すところにまで落とされる。

さて、hash_appendは、operator ==と密接に関係している。すなわち、

  1. x == y ならば、xとyは、hash_appendに同じメッセージを送る
  2. x != y ならば、xとyは、hash_appendに異なるメッセージを送る

オブジェクトが等しいならば、同じハッシュ値が計算されて欲しいので、同じ情報が送られなければならない。オブジェクトが等しくないのであれば、異なる情報が送られなければならない。ということだ。

たとえば、vectorを考える。vectorのoperator ==は、size()を比較してから、要素を比較すると定義されている。このため、vectorのhash_appendは、size()をハッシュ計算のメッセージとして送るべきである。

なぜか。もし、size()がハッシュ計算に使われなければ、以下の二つのオブジェクトが、ハッシュ計算では等しいメッセージとして見えてしまう。

std::vector<std::vector<int>> v1{};
std::vector<std::vector<int>> v2{1};

もしsize()をハッシュ計算に使わないと、v1は空なので何もメッセージを送らない。v2は内側のvectorを送るが、内側のvectorは空なので、ハッシュ計算に使うべき情報を送らない。したがって、どちらも同じメッセージになってしまう。

このため、size()をハッシュ値計算に混ぜ込む必要がある。問題は、size()は先に送るか後に送るかということだ。先に送る場合、std::forward_listのようなコンテナは、size()を計算するのにコストがかかるため、コンテナーは後に送るということで統一しようと論文は提案している。

ハッシュ値の計算には、contiguously hashableという概念がでてくる。これは、あるT型の任意の値x, yに対して、x == yならば、memcmp(addressof(x), addressof(y), sizeof(T)) == 0 がtrueとなることである。つまり、x == yならば、xとyは全く同一のビットパターンを持たねばならない。また、パディングビットのような、任意の値を取れるようなビットがあってはならない。

論文では、ある型Tがcontiguously hashableかどうかを調べるtraits、is_contiguously_hashable<T>を提案している。

整数が2の補数表現の環境の場合、intはcontiguously hashableである。

IEEE浮動小数点数は、contiguously hashableではない。なぜならば、0 == -0ではあるが、0と-0のビットパターンは同一ではないからだ。したがって、IEEE浮動小数点数を使う環境では、ハッシュ計算には特別なはからいをしなければならない。

boost::hash_combineとの違いは、hash_appendはビット列をそのまま送り込むのに対し、hash_combineは、個々にハッシュ値を計算し、複数のハッシュ値から、そこそこ使えるハッシュ値を計算するものである。hash_appendの方がハッシュ値計算をネイティブにサポートしている。

hash_appendはVariadic Templatesで実装されていて、引数をいくつも渡せる。

現在、ハッシュ計算としてよく使われているアルゴリズムで、N3980提案で効率的に実装できないものに、CityHashがある。これはCityHashは、後ろから計算していくためである。

とはいっても、CityHashと同等の計算速度や品質をもったアルゴリズムは他にもあるので、CityHashを考える必要はないとしている。

また、このライブラリは、SHA-2などのセキュアなハッシュ値計算に使うためにも転用できる。

pimplにどのように対応するかという問題は、HashAlgorithmをstd::functionでラッパーしてtype erasureすることにより、仮想関数呼び出しで実行時に呼び出し先を決定することができるとしている。

また、unorderedコンテナーのハッシュ計算は、同じ数と値の要素をもつコンテナー同士で同一のハッシュ値を計算する方法は、ないこともないが、どれも一長一短で、汎用的な方法がないため、この提案では規定しないとしている。

この論文を読むのは時間がかかった。

N3981: Removing trigraphs??!

トライグラフを規格から削除する提案。タイトルが面白い。??!はトライグラフで|に置換される。

ある巨大なコードベースに対して、トライグラフ風の文字列を検索した所、

  • 923件のトライグラフ置換を防ぐためにエスケープされた?

    string pattern() const { return "foo-????\?-of-?????"; }
    
  • 4件のトライグラフが、意図的にテストコードで使われていた。コンパイラーのためのテストコード2件と、boostのプリプロセッサーライブラリのテストコード2件。
  • 0件のトライグラフが、意図的にプロダクションコードで使われていた。

明らかに、トライグラフはC++の足かせになっている。

論文は、規格からトライグラフを削除する提案をしていて、そのための文面も提示している。

N3982: Rvalue reference overloads for optional

optionalのメンバー関数、valueとoperator *にref-qualifierがrvalueリファレンス版のオーバーロードを追加する提案。これはむしろ、バグフィクスと言える。

[せっかくやる気になっていたのに忌々しいPDF] Hashing tuple-like types

N3980とは違って控えめな提案。

std::pair, std::tuple, std::arrayをstd::hashに対応させる提案。これにより、tupleなどをunorderedコンテナーに突っ込める。

[嫌気が差すPDF] N3984: Adding attribute reflection to C++.

よくわからない変な提案。TSへの提案のようだが、あまりに違和感を覚える機能のためだろうか。また、どうもサンプルコードに誤りが多い。

どうも論文の記述が詳細ではないので、よく理解しにくいが、この提案は、クラスに、初期化子が書かれたattributeをクラスに付加し、typedefキーワードを使った文法でconstexprインスタンスとして取り出す機能である。typedefキーワードを使った文法は、N3951提案を拡張している。


struct serializable { } ;

struct getter { std::string name ; } ;
struct setter { std::string name ; } ;

struct [[serializable]] X
{
private :
    int index_ ;

public :
    [[ getter{"index"} ]] int index() const { return index_ ; }
    [[ setter{"index"} ]] void set_index( int value ) { index_ = value ; }
} ;

// std::make_tuple( serializable() )  
auto t1 = std::make_tuple( typedef<[[X]]>... ) ;

// std::make_tuple( getter{"index"} ) 
auto t2 = std::make_tuple( typedef<[[&X::index]]>... ) ;

// std::make_tuple( setter{"index"} )
auto t2 = std::make_tuple( typedef<[[%X::set_index]]>... ) ;

このように、クラスやメンバーにattributeを付加し、またtypedefを使って、constexprインスタンスとして取り出すことができる。

また、typedefにはrequires Cという文法で、取り出すattributeをフィルターできる。Cはテンプレート型引数ひとつとり、typedefでattrributeが返されるか否かをboolを返すconstexpr関数である。


struct Bogus { std::string str ; } ;
struct FuckingWhat { std::string str ;} ;
struct this_attribute_is_bullshit { std::string str ; } ;
struct awesome { std::string str ; } ;

template < typename T >
constexpr bool is_awesome
{
    return std::is_same_v<T, awesome> ;
}

struct [[
    Bogus{"Don't mind me."},
    FuckingWhat{"Seriously, I am useless attribute."},
    this_attribute_is_bullshit{"What did you expect huh?"},
    awesome{"I am just awesome."} ]]
X { } ;

/*
    std::make_tuple(
        Bogus{"Don't mind me."},
        FuckingWhat{"Seriously, I am useless attribute."},
        this_attribute_is_bullshit{"What did you expect huh?"},
        awesome{"I am just awesome."}  ) 
*/
auto t = std::make_tuple( typedef<[[X]] >... ) ;

// std::make_tuple( awesome{"I am just awesome."} ) 
auto t = std::make_tuple( typedef<[[X]] requires is_awesome >... ) ;

また、has_attribute<X, A>というtype tratisが追加される。これは、ある型XがattributeとしてA型、もしくはAから派生する型を持っている場合trueを返す。


struct Base { } ;
struct Derived { } ;

struct [[ Derived ]] X { } ;

std::has_attribute_v<X, Base> ; // true
std::has_attribute_v<X, Derived> ; // true

まあ、使い方はいろいろあるだろう。しかし、どうも個人的に、あまりにも文法や意味がわかりにくいコードに思えてならない。

[PDF注意] N3985: A proposal to add coroutines to the C++ standard library (Revision 1)

コルーチンライブラリの提案。Boost.coroutineを土台にしている。

とても重たい論文なので、軽く紹介するだけにとどめるが、std::asymmetric_coroutine<T>とstd::symmetric_coroutine<T>が追加される。

asymmetricなコルーチンとは、コルーチンが呼び出し元を把握していて、特別な操作によって、呼び出し元に実行を返すものである。

symmetricなコルーチンとは、呼び出し元だけではなく、任意のsymmetricなコルーチンに実行を移せる。

[PDFは切り詰められるべき] N3986: Adding Standard support to avoid padding within structures

クラスのパディングを無効にする文法を追加する提案。

C++では、クラスのサイズがいくつになるかは、規定されていない。

以下のようなコードを考える。

struct SomeDataStructure
{
    uint8_t type ;
    uint32_t data ;
} ;

ここで、sizeof(SomeDataStructure)は、1 + 4とはなる保証はない。たとえば、あるアーキテクチャでは、メモリは適切にアラインされていなければならないという制約があるかも知れない。そこで、コンパイラーはパディングと呼ばれる詰め物を挿入して、アラインを合わせようとする。

// このコードはパディングがないものとする
struct SomeDataStructure
{
    uint8_t type ;
    uint32_t : 24 ;
    uint32_t data ;
} ;

また、以下のようなコードを考える。

struct SomeHeader
{
    uint8_t : 4 ;
    uint8_t valid : 1 ;
    uint8_t : 1 ;
    uint8_t id : 2 ;
} ;

この場合、sizeof(FogFrameHeader)が1になる保証はない。なるほど、4 + 1 + 1 + 2は8ビットだが、コンパイラーがパディングを挿入しないという保証は、規格上存在しない。

しかし、このようなコードは、ビット列とその位置が重要なのであって、パディングを挿入してもらいたくないのだ。現実のコードでは、ディスク上のフォーマットや、ネットワークパケットのフォーマット、あるいはメモリを節約するハックなど、ビット列をパディングなしで明示的に指定したい需要が多くある。

このため、主要なC++コンパイラーには、パディングを無効にする独自の機能が提供されている。したがって、パディングを無効にする機能は、標準で存在すべきである。

N3986提案では、既存のビットフィールドの文法を拡張して、-1が指定された場合、次のビットフィールドをアラインせず、すなわちパディングを無効にする意味を持つ。

struct SomeDataStructure
{
    uint8_t type ;
    uint8_t : -1 ;
    uint32_t data ;
} ;

struct SomeHeader
{
    uint8_t : 4 ;
    uint8_t : -1 ;
    uint8_t valid : 1 ;
    uint8_t : -1 ;
    uint8_t : 1 ;
    uint8_t : -1 ;
    uint8_t id : 2 ;
} ;

もし、クラスSの-1ビットフィールドの次のメンバーtがビットフィールドではない場合、そのメンバーのオフセットは、offsetof(S, t) % sizeof(t) == 0を満たす必要がある。

struct S
{
    uint8_t c ;
    char : -1 ;
    uint32_t t ;
} ;

static_assert( offsetof( S, t ) % sizeof(t) == 0, "This shall not be asserted" ) ;

これはTS行きなのかもしれないが、パディングを無効にする機能は、標準で欲しいところだ。

[Yet another goddamn PDF] N3987: Yet another set of C++ type traits.

小粒だが有益な型情報を得るtype traitsを多数追加する提案。

is_default, is_delete, is_extern, is_explicit, is_export, is_final, is_friend, is_inline, is_mutable, is_noexcept, is_override, is_private, is_private_base_of, is_protected, is_protected_base_of, is_public, is_public_base_of, is_thread_local, is_virtual, is_virtual_base_of.

is_defaultとis_deleteは、default化やdeleted定義されたメンバー関数ならばtrueを返す。暗黙にdefault化やdelete定義された特別メンバー関数の場合はどうなるのだろうか。他にも、デストラクターは例外指定を基本クラスから暗黙に受け継ぐ。クラス定義内で定義されたメンバー関数は暗黙にinlineになる。こういう暗黙の型情報はどうなるのだろうか。

論文筆者に問い合わせたところ、明示的であろうが暗黙であろうが、結果には影響を及ぼすべきではないとの回答を得た。論文ではこの問題について明示的に考察していないが、するべきだと思われるので、次の改定版では言及するとのこと。また、暗黙的に指定されたかどうかを調べるis_implicitが必要かもしれないと言っていた。

また、ローカルクラスかどうかを返すis_localや、is_pure_virtual, is_ovberload, is_direct_base_ofなどといったtype traitsも挙げられている。

[PDFだ・・・] N3988: Towards restrict-like aliasing semantics for C++

C++にC99のrestrictの機能を入れるにあたっての議論をまとめた論文。

C99のrestrictを単純にC++に入れられない理由は、thisポインターを経由するクラスメンバーへのアクセス、リファレンスへのrestrict、restrictの有無がオーバーロード解決やテンプレート実引数推定に影響するかどうか、またlambdaキャプチャーなど、C99にはない問題を考える必要があるからである。

しかし、現実の主要なC++コンパイラーを観察すると、すべての主要なコンパイラーは、restrictキーワード、あるいは同等機能を、何らかの方法で実装している。明らかに需要がある。これは標準化が必要だ。

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

<algorithm>にタグディスパッチで並列実行版とベクトル実行版を加えるTS(Technical Specification)への提案。

ドワンゴ広告

この記事はドワンゴ勤務中に書いた。これを書いている最中に、筆者の近くの席から、「ああ! 一瞬死んでもらえばいいのか!」という会話が聞こえてきた。実に、プログラマーの会話というのは、文脈を離れると物騒になるものである。

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

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

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

2014-06-24

ドワンゴC++勉強会のニコ生の番組宣伝

ドワンゴ広告

6月28日にドワンゴのセミナールームで行われる、ドワンゴC++勉強会 #1の、当時のニコニコ生放送の番組URLができた。

ドワンゴC++勉強会 #1 - 2014/06/28 14:00開始 - ニコニコ生放送

ドワンゴC++勉強会は、ニコ生による映像配信が行われる手はずになっている。

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

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

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

ドワンゴ非広告

今、N3985を読んでいる。これはコルーチンをC++の標準ライブラリに追加する提案だ。設計は、Boost.Coroutineを土台にしている。よく書けている論文ではあるが、なかなか読むのに時間がかかる。今月は、個人的な環境に大変化が多数あったため、C++WG論文の読み込みが遅れている。さらに7月に次の論文集が控えているので、しばらく忙しくなるだろう。ちなみに、これはドワンゴにおける筆者の仕事ではない。ただ勤務中に勝手にやっているという扱いになっている。

妖怪ハウス宣伝

6月27日、28日の夜は、妖怪ハウスにあのボレロ村上氏が来るため、妖怪ハウスに来ると技術的な話で盛り上がれるだろう。何か大人数で食べられる食事を作ろうと思う。

7月6日は、妖怪ハウスでピザでも焼きながら、ボードゲーム会でもしようと思っている。

妖怪ハウスに来たい人は、筆者のTwitterかメールに連絡をすればよい。

2014-06-23

妖怪ハンモックその他の雑多な感想

ハンモックの話

妖怪ハウスにハンモックを導入したことは、すでに述べた。ハンモックは土台付きのものを買ったのだが、ついてきたハンモックは、あまり寝心地がよくない。調べると、もっと良さそうなハンモックも売られている。ハンモックの布自体は、それほど高くない。そこで、もう一枚ハンモックを買うことにした。

買ったのは OUTDOOR EX 2人用 耐荷重 200kg 布製 ハンモック 専用ポーチ 補強帯 S字フック 付 ストライプ(レインボー)だ。これは、耐荷重200kgで、相当に幅も広い。二人用だという。ひとつのハンモックで二人寝る場合、相手の選択は自然と選り好みをする必要があるだろうが、それはまた別の話だ。今回は一人で寝る快適性のみを検証する。

アマゾンで買って、すぐに届いたので、早速にも寝心地を検証したかったのだが、あいにくと、手持ちの土台には長さが余りすぎて取り付けられなかった。ベランダの手すりになら取り付けられそうだが、それにはテントをたたまなければならない。雨が上がったら試すつもりだ。

ところで、今週末、来週末は、どうやら妖怪ハウスに来ると面白くなりそうだ。

6月27日,28日は、岡山から陶芸constexprプログラマーの某氏がやってくるので、ちょっとしたパーティでも開こうと思っている。

また、7月6日は、ピザパーティでもしようかと思っている。どうやら、妖怪ハウスに遊びに来るには、何らかの口実が必要であると考える人が多いらしい。確かに、私もシェアハウスめぐりを続けたいと思っているが、最近は新しいシェアハウスには行っていない。いつ来てもいいとは言われていても、パーティなどの、何らかのいくための口実が必要だ。そこで、7月6日はピザでも焼きつつ残りのタピオカパールをゆでつつ、また適当な菓子でも作って人を呼び、ボードゲームパーティでもしようかと思う。

ストレスへの対処方法の話

最近、ストレスへの対応方法が真逆の人間を二人観測している。一人はストレスの発散として破壊活動を行う。もう一人は、ストレスを貯めこんで自己の肉体を破壊している。どちらがマシだろうか。私は前者のほうがまだマシである気がしてならない。その破壊対象が私と私の所有物に及ばなければの話だが。

SI屋の話

10年ほど前、筆者は当時2ch.netのプログラマー板で、SI屋の悲惨な現状を観測していた。その当時、下手な受注ソフトウェア開発会社に雇用されると、数年以内に精神を壊し、再起不能に陥るだろうと結論した。そのため、私は職を求めずに、己の欲するところを行った。その結果、今の不思議な立場を得た。今の立場を得る見込みは当時一切なく、またこの後何年続くかもわからないが、少なくともこれだけは言える。SI屋で働くよりはマシだ。

SI屋の問題は、結局、ソフトウェアやプログラミングという概念自体が理解できないバカな顧客を相手に利益を上げるところから来るのであろう。利益を最大にしようとすると、バカな顧客でも理解できそうなバカで無駄で不必要な作業を行って、その作業に金が必要なのだと説得にかかる。そして、顧客から金を得た以上、実際にバカで無駄で不必要な作業を行う。

住み分けてもらいたい。本物のプログラマーの素質を持った人間を、SI屋で潰さないでもらいたい。

東京に出てきてから半年たった話

東京に出てきてから、もう半年たった。実に、筆者の環境は劇的に変化した。環境の劇的な変化は、今も続いている。また、意図的に変化させるようにしている。

それにしても、周りの環境は劇的に変化したが、筆者自身は、あまり変化した実感がない。筆者は一つのことは数ヶ月で飽きるので、興味の対象がどんどん変化する。そういう意味では、東京に出る前と、あまり変わっていない日常と言える。

2014-06-22

Eric Meyerのレベッカに対する弔辞

Eric's Archived Thoughts: Eulogy

以下はレベッカの葬式における私の弔辞である。私が当日言ったこととテキストが一致しているといいのだが。この言葉を引き出した悲しみにより、私は正確な言葉を覚えていないし、また撮影された映像を見返す気力も今はない。五木力が湧くのかわからない。いつか見て、Carolynの言葉を聞きたいものだ。

レベッカはわんぱくであった。娘は生後二週間で、にらめっこコンテストで大人を負かした。レベッカは元気だった。娘の笑い声は部屋中に響き渡り、皆をほほ笑ませた。レベッカはがんこだった。たとえ、欲しい物を失ったとしても、娘は絶対に諦めなかった。レベッカは優しく、愛しく、わがままで、ああ、くすぐったがりだったな。

レベッカはやんちゃだった。歩くぐらいならスキップ、スキップするぐらいなら走る、走るぐらいなら踊る、踊るぐらいなら物陰に隠れて追いかけてきた人を脅かす。

娘は携帯電話や財布やカギをポケットから盗むのが好きであった、隠すのではなく、悪いことをするのでもなく、目の前で振りかざして、歌い踊るのであった。これ以上のことは、どうか娘から遠ざけてもらいたい。娘が到底できっこないことを目指すのを防ぐためではない。むしろあまりにも簡単にできてしまい、がっかりするのを防ぐために。

レベッカは天使ではなかったし、本人も天使となりたいとは思わなかった。レベッカは、いわばポルターガイストだ。六歳の誕生日に、その日と次の日は、遊園地に行こうと決めていた。そうとはならず、娘の命日となるとは。その日、水道管の故障により、遊園地は週末閉園した。娘が行けないのであれば、誰も行くべきではないからだ。今朝このことを話していて、私がまさに「電気なんか消えてしまえ」と言わんとしたとき、家が停電した。

ややクサい話だ。

娘の最後の数週間は、腫瘍が娘から元気をゆっくりと奪っていき、とてもつらかった。元気のない娘を見るのは耐えられなかった。娘の日常生活を快適にするために長年努力してきて、うまくいっていた。最後の数日は、その努力すらも無駄であった。

娘は、いつまでもレベッカであった。娘は兄弟が親のそばにいるのに、自分は近寄れないことに腹を立てていた。娘は兄弟のせいではないために、兄弟を許した。我々が娘を楽しませようとする努力がつまらないがために、娘は見下げた顔を向けた。娘は言葉もなく、しかし明らかに、大好きなお話をせがんだ。娘は、我々をこれ以上苦しめないよう、我々を遠ざけようとした。だが、我々の愛はいかなる苦しみにも代えがたいものであり、この愛は決して消えることがないと説明した時、娘はこの疑いようのない真実を認めた。娘の最後の言葉と仕草は、愛であった。

娘の最後の数時間は悲痛であった。一緒であったからこそ乗り越えてこられたのだ。コミュニティは我々を数カ月の間支えてくれ、レベッカとキャロラインと樹脂あのために、できる限りのことができた。コミュニティはこの問題を乗り越えさせてくれた。我々の心は数え切れないほど粉々のかけらになったが、拾い集めて元に戻す助けとなるだろう。娘がいなくなり、私は心を壊す以上に参っているが、私は決して、一瞬たりとも、娘を我が家に、我が生活に加えたことを後悔しない。

人生とは、自分が何を成し得たかではなく、他人に何を成し得たか、どんな業を残したが重要だ。娘の人生は短かったが、その光は時代に照り輝き、多くの人の心を温め、我々の残りの人生をより良くしてくれた。

妖怪ハウスにハンモックを導入した

さて、これまで妖怪ハウスには、レトロゲーム、まともなネットワーク機器、ゴミ箱、メタルラック、テント、大きな冷蔵庫、乾燥機付きの洗濯機など、様々なものを導入してきた。これにより、妖怪ハウスはだいぶ住みやすくなった。

しかし、まだ妖怪ハウスに欠けているものがある。ハンモックだ。

来たるべき夏に、ベランダにハンモックを設置して寝たら、さぞかし気持ちがよかろう、

なるほど、ハンモックはよろしい。しかし、ハンモックを吊るすべき場所がない。調べると、ハンモックを固定する土台が売っているようだ。これならば、十分な空間さえあれば、どこでもハンモックを設置できる。。

ハンモックは、東京に来た時から買いたかったが、色々と忙しく、また外も寒かったため、買わずにしまった。しかし、そろそろ余裕も出来たので、ひとつ買ってみることにした。アマゾンでは、手頃な商品として、7700円のMサイズと、14000円のLサイズのものがあった。せっかくなのでLサイズを買ってみることにした。

さて、ハンモックは昨日届いた。喜び勇んで開封し、ひとまずリビングに設置した。そして、その快適な寝心地に感動した。

その晩はハンモックで寝ようかとも思ったのだが、慣れない環境では睡眠の質が下がる可能性があるため、テントで寝た。夜間、激しく雨が降ったが、予め施しておいた防水対策で、こんどは浸水することはなかった。

ハンモックに対するさしあたっての不満は、袋から開封したばかりのネットが、何か接着剤のような臭いがするということだ。これは一度天日干しにする必要があるだろう。それには梅雨明けを待たねばなるまい。

rebeccapurpleがCSS 4 colorに提案された経緯

Name #663399 "Becca Purple" in CSS4 Color? - Specifiction

#663399を"Becca Purpule"としてCSS4 Colorに入れないか?

CSS colorに名前を追加する方法はわからないし、なにか目的に叶うものであるかどうかもわからないが、@meyerwebのCSSに対する貢献を明らかにするために、また標準化というのはそもそも社会的プロセスによって進められることを明らかにするために、#663399を"Becca Purple"と名付けないか?

これはいったいどういうことか。Beccaというのは、哀れにも六歳にして亡くなったEric Meyerの娘の名前なのだ。Eric MeyerはCSSの標準規格に尽力し、また、 Cascading Style Sheets: The Definitive Guideや、 Css Pocket Referenceといった本を執筆している。彼のCSSに対する貢献は甚大であり、彼の亡くなった娘のために、提案されたのだ。

この提案に対する、彼の声明は以下の通り

Eric's Archived Thoughts: rebeccapurple

beccapurple(#663399)をCSS規格に追加しようという提案と、その提案を取り巻く議論についてはすでに把握している。

この提案に対する賛成と反対意見のそれぞれについては理解できるが、明らかに、私はこの問題に立ち入って判断するには、あまりにも個人的に問題に密接すぎる。ついては、わたしはColor規格のエディターに、Working Groupの総意がどうあれ、受け入れることを伝えた。現在、WGはこの提案を議論中である。

私は条件をひとつだけ出した。もし、提案が受け入れられるならば、名前はrebeccapurpleでなければならぬ。私の娘が死ぬ数週間前、レベッカは、ベッカは赤ん坊の名前であり、六歳になったらビッグになってやるんだ、と我々に宣言した。六歳になった時、娘は自分のことは(単に私だけではなく皆から)ベッカではなくレベッカと呼んでほしいと望んでいた。

娘は6歳になった。十二時間もの間、娘は六歳であったのだよ。だからレベッカだ。レベッカでなくてはならぬ。

Katと私はコミュニティが気にかけてくれたことと支援に深く感動している。この提案は、個人的にとても大きなものである。たて、この提案が最終的に否決されたとしても、とても大きな意味を持つものである。私は常々、「推奨されるのは光栄である」というのは、すっぱい葡萄の上で踊るようなものであると考えていたが、どうやら違うようだ。本当に光栄である。結果がどうなるにせよだ。光栄であるにせよ、誰もそういうことを考えてのことではないのだから。

みんなありがとう。

Rebeccaの死の経緯

Eric's Archived Thoughts: The Truth

小さな小児精神科病院の低い壁際にあるソファに、レベッカを座らせた。レベッカはKatの膝の上に登り、私を、恥じらいといたずら心の入り混じった独特の表情で見た。私は娘の我々に寄せる信頼と、これから娘に伝えねばならぬことに耐えかねて呼吸困難に陥っていた。

「お前には言わなくちゃならないことがあるんだよ」

娘は目を伏せた。娘の表情なにか悲しげなものに溶けていった。知っているのだ、と私は考えた。知っているのだ。しかし、いずれにせよ我々は言わねばならぬのだ。

「悪い石のこと、覚えてる?」 娘は無表情に、ゆっくりと、とてもゆっくりと、体を持ち上げた。「お医者さんが取り除けなかった、頭の中にある腫瘍のことは覚えている? パパとママが悪い石を消すお薬を探していたのを覚えている?」

我々は娘が頷くのを待った。娘がこの問題を理解しているという証拠を。しばらくして、娘は逃げ場を探すように、キョロキョロしだした。

「お薬は見つからなかったよ。まだ探してるんだが、見つからないかもしれない」Katの顔から涙がたれた。私も顔を伏せているので、レベッカの顔をよくみることができぬ。娘は顔を下げて、Katから離れ、我々夫婦の間に座を占めた。

小さな、うめくような声「お前、分かっているのかい?」

沈黙

娘は頷いた。そして、顎が震え始めた。沈黙。さらにさらに震え始め、顔が歪み、すすり泣き始めた。後ろザマにのけぞり母親にもたれかかり、まだボールのように丸まりながら、絶望に泣く。避けられぬ死に対して。

我々三人はみな抱き合ってすすり泣いた。

上手く訳せないので、後はリンクのみ。

他にもまだあるので、Eric's Archived Thoughts: Rebeccaで。

訳し忘れていたが、rebecca purpleは規格入りするようだ。

Re: [CfC] adding 'rebeccapurple' color to CSS Color Level 4 from Daniel Glazman on 2014-06-21 (www-style@w3.org from June 2014)

From: Daniel Glazman <daniel.glazman@disruptive-innovations.com> 
Date: Sat, 21 Jun 2014 09:48:06 +0200
Message-ID: <53A538B6.3090400@disruptive-innovations.com> 
To: "www-style@w3.org" <www-style@w3.org> 

(co-chair hat on)

以下の提案はソーシャルメディアで公開された。この提案は、カラー名、rebeccapurpleを、値#663399にて、CSS Color Level 4に追加するものである。これは最近亡くなられたEric Meyerの娘を記念して、WebコミュニティがEricに支援を表明するためのものである。私は念の為にEricに了承を求めたが、Ericは「光栄に思い、喜んで受け入れる」と返答した。

一部の実装者(MOzilla, Apple, Google, Microsoft)は、この新しい値を実装してリリースすると明言している。

そこで、この提案へのコンセンサスを呼びかけるものである。

太平洋時間金曜日11:59PMまでに反対意見のないかぎり、私はコンセンサスが得られたものと宣言し、値をCSS Color Level 4に追加する。

期限までに反対意見がこのCfCに寄せられることはなかったので、私はコンセンサスを宣言する。Tab、'rebeccapurple'をCSS Color Level 4に付け加えてくれ。

記録のために書くと、私がEricにこの決定を連絡するように勧めたのはTabだ。なぜならば、EricがこのWGに在籍していた時、私も在籍していたからだ。私は今日中に連絡しておく。CSS WGを代表するのみにあらず、我々Webコミュニティ全体の代表として。

おめでとう!

</Daniel>

2014-06-19

Debianがeglibcからglibcに戻る

Debianはしばらく、libcとして、glibcではなく、glibcと互換性を維持したforkであるeblicを使っていたが、このたび、glibcに戻る決定をしたそうだ。

glibcを使っていた理由はいろいろあるが、Debianにとって重要なパッチが、glibcでは開発体制の問題により受け入れられないという政治的な理由もあったそうだ。その問題が解決されたのと、eglibcがプロジェクトとして死んだので、戻るのだそうだ。

Debian is switching (back) to GLIBC | Aurelien's weblog

5年前、Debianと多くの派生ディストロは、標準であるGNU C Library (GLIBC)から、Embedded GLIBC (EGLIBC)乗り換えた。Debianは、GLIBCに再び乗り換えることにする。EGLIBCの最後のリリースは2.19と、プロジェクトとして死んでいるからだ。現時点で、glibcパッケージがexperimentalにアップロードされ、 NEW queueにある。

EGLIBCが死んだのは、物事が良い方向に変わってきたからだ。GLIBCの開発体制は、ここ数年で、二つの大きな事件により、大きく変わった。Ulrich DrepperがRed Hatを辞めて、GLIBC開発から手をひいたのと、GLIBC steering committeが自然消失したからだ。この結果、協力的なチームワークによる友好的な開発体制に変わった。開発は今やピアレビューを基本とし、結果として不具合が減少した(人間は誤りを犯すものである)。昔ならば不可能であったことも可能になった、例えば、すべてのアーキテクチャで、同じレポジトリを使うとか、ports/ディレクトリを廃止するとかだ。かつては、二つのアーキテクチャー群に分かれていた。x86とかSuperHとかSPARCなどの主要アーキテクチャーは、主要レポジトリであるglibcレポジトリで、ARMとかMPSなどのアーキテクチャーは、副レポジトリであるglibc-portsレポジトリでサポートされていた。明らかに、分離には明確な理由はなく、変更が副レポジトリに適用され忘れることも多かった。それから、定期的な修正が行われる、本物の安定ブランチもできた。

ほとんどの重要なEGLIBCの機能はGLIBCにマージされた。例えばbashではなくPOSIXシェルを使うとか、予約語を変えるとかだ。まだマージされていないのは、設定可能なコンポーネントだ。これは、 Debian-インストーラーで使う予定で、NISとk PRCをサポートせず、-Osを使った軽量版を作るとかだ。結局、そういう開発はしなかったし、Debianの対象となるハードウェアは、GLIBCのサイズより早く発展していったので、それほどの損失ではない。最終的に、EGLIBCのツリーから取り込まれなかったパッチは、5個だ。

パッケージ名は変更されない(ソースパッケージとソースを含むバイナリパッケージは除く)ので、ユーザーからは変更は意識されない。

EGLIBCのために働いてくれたCodeSourcery社員と、EGLIBCの主要な変更をGLIBCにマージするために多大な時間を割いてくれた上に、マージ状態に関するメール定期的送ってくれた、Joseph Myers感謝する。そして、GLIBCの改革を実現してくれたGLIBC側の人々と、GLIBC開発に関わったすべての人々に感謝する。

ちなみに、Red Hatを辞めたUlrich Drepperは、ゴールドマン・サックスに移ったのだが、Reddit上では、これは2008年の経済問題を引き起こした張本人を罰するために移ったのだというジョークが書かれている。

Debian is switching back to GLIBC | Hacker News

結局、独裁者の存在は、長期的に見れば損失が大きい。