2010-08-29

バイク小屋議論

Rapperswill会議で、すでに決定されたことがある。attribute-tokenのうち、final、override、hiding、base_checkを、本物のキーワードを使う文法に置き換えようというものである。

たとえば、以下のように書くべきだったコードを

struct Base
{
    virtual void f() { }
    int value ;
} ;

struct [[ final, base_check ]] Derived
{
    [[ override ]] virtual void f() { }
    [[ hiding ]] int value ;
} ;

キーワードを使った文法にする。例えばの話だが、以下のようになるかもしれない。

struct Base
{
    virtual void f() { }
    int value ;
} ;

struct final_overrider verify_decls Derived
{
    virtual void f virtual_override () { }
    int value hiding_name ;
} ;

見ての通り、非常に汚いキーワードである。しかし、これは真面目に提案されたキーワードである。本物のキーワードを導入するということは、その名前を使っている既存のコードをすべてぶち壊すということである。したがって、絶対にかぶらないであろう名前しか使うことはできない。その結果、このようなキーワードになる。また、文法も、specifierのように宣言の前に書けるようにするか、identifierの後ろに書くようにするかで揉めている。前置するとなると、以下のようになる。

struct Base
{
    virtual void f() { }
    int value ;
} ;

final_overrider verify_decls struct Derived
{
    virtual_override virtual void f() { }
    hiding_name int value ;
} ;

少しはマシだろうか。とはいえ、キーワードの醜さは変わりない。

これを見て、どう思うであろうか。attributeとキーワードと、どちらを好むであろうか。教えて欲しい。因みに私は、こんな汚いキーワードを使うぐらいなら、attributeの方がマシだと考えている。

こうなった理由は、attributeというのは、あくまで独自拡張用の機能であり、標準規格が積極的に使うべきではないという考えからのようだ。しかし、それをいえば、各ベンダーだって、キーワードを使ったもっと分かりやすい文法の方がいいと考えはしないだろうか。その結果、MSVCの__declspecや、gccの__attribute__がでてきたのだから。そんな考えでは、attributeはasm宣言と同じく、実装から無視されるのではあるまいか。

ちなみに、このタイトルである「バイク小屋議論」というのは、この問題を議論していた標準化委員会のMLのタイトルが、"Bikeshedding, yay! (keywords for override control attributes)"だったからである。

Javascriptによるファミコンとゲームボーイのエミュレーター

JavaScript NESエミュレータ とか
JavaScriptでGBエミュを作ってみた(音を出してみたVer.)‐ニコニコ動画(9)

Javascriptによるファミコンとゲームボーイのエミューレーター。audio要素を使って、音まで出しているらしい。一体どうしているのかとソースを読んだところ、生成したPCMストリームを、base64にエンコードした上で、"data:audio/wav;base64"でaudio要素のsrc属性に指定して、流し込んでいるようだ。なるほど、その手があったか。

しかしやはり、Javascriptには生のビット列を扱う方法があらまほしい。

ここまできたら、あとはゲームパッドに対応するだけだ。しかし、Flashによるゲームが沢山あることを考えると、必須ではないだろう。

post Rapperswil mailingが公開された

ISO/IEC JTC1/SC22/WG21 - Papers 2010

最新ドラフトは、N3126になった。もっとも、このドラフトには、今回のRapperswill会議で、変更すべきだと決定された変更の全ては含まれていない。まだ、細かい文面を考案中だからだ。

また変更点を確認して、いま執筆中の参考書の、すでに書き終えた部分との齟齬を確かめる作業が始まる。

N3103: Security impact of noexcept

単なる例示のためのペーパー。noexceptとマークされた関数が、例外を外に投げた場合、直ちにterminateする。このルールが守られない場合、具体的なある実行環境で、セキュリティ上の問題を引き起こす。したがって、かならず実装はterminateしなければならない。

N3106

min/max/minmaxにおける、文面の変更間違いの修正。

N3108

std::basic_stringの最適化手法として、現在主流の、small-string optimizationというものがある。詳しくは解説しないが、まあ、以下のようなものだと思ってくれればいい。

// charの文字列を格納するクラス
class String 
{
    char * ptr ; // 動的に確保するストレージへのポインター
    size_t size ; // ストレージのサイズ
    // 文字列長が十分に小さい場合、こっちを使う
    char small_string_buffer[8] ;
} ;

std::stringに格納する文字列が、わずか数文字というのは、よくあるケースである。そのような場合、特別にsmall_string_bufferを使えば、わざわざ動的にストレージを確保する必要がなくなる。

さて、std::basic_stringは、コンテナーの要件を満たしている。ところが、新しいswapの定義を満たそうとすれば、このsmall-string optimizationが使えなくなる。このため、std::basic_stringに限り、swap後のイテレーターが無効になるという条件を付け加えて、このような最適化ができるようにする提案。

N3109: US 108

C++0xにrvalueリファレンスを付け加えた目的とは、rvalueに対するMove semanticsのためである。auto_ptrのようなlvalueに対するMove sematnicsを提供するライブラリは、deprecatedである。そのため、unique_ptrのコンストラクターは、rvalueのauto_ptrだけを引数に取るようにする。lvalueのauto_ptrを引数にとるコンストラクターは削除する。

N3110: Problems with bitmask types in the library

iostreamのビットマスクとかアホすぎだから、付け焼刃的になんとかしようという提案。iostreamは設計自体が腐っているので、どうせアホなことには変わりないのだが。

N3112: Proposed Resolution for CH 15

Pittsburgh会議でMoveコンストラクターとMove代入演算子の意味を変えたが、その変更が、ライブラリの既存の文章に影響を及ぼしている。それに対する修正。

N3113: Async Launch Policies (CH36)

asyncのlaunchには、三つのオプションがある、async、sync、anyである。anyとは、asyncでもsyncでもない実装依存の方法ということになるのだが、そんなあやふやな定義では、ベンダーはまともに意味のある実装を提供することはできないし、ましてやユーザーは、ポータブルなコードを書くことができない。そのため、これを実装依存の識別子ということにする。

また、syncという名前は誤解を招きやすいので、deferredと改名する提案。

単に私の英語力が拙いだけなのかもしれないが、defferredといい、futureといい、どうも同期周りには、非ネイティブには、一見して意味の分かりにくい名称のライブラリが多い気がする。

N3114 - throw() becomes noexcept

タイトル通り、ライブラリのthrow()をnoexceptに変更する提案。

N3122: Observers for the three handler functions

C++0xには、マルチスレッドという概念が入る。そうなると当然出てくる問題は、データ競合(data race)である。このため、operator newとoperator delete、さらにCライブラリのcalloc/malloc/realloc/freeは、データ競合を引き起こしてはならないと規定された。

この制約は、ユーザーによるoperator newとoperator deleteのオーバーロードの際にも、当然守らなければならない。しかし、set_new_handlerは、値を変更しつつ、先の値を得るという仕様である。とすれば、set_new_handlerの仕様には、何らかの排他的処理を講じなければならないが、ユーザーコードとライブラリコードとの間での共通の排他的処理というのは無理である。とすれば、ユーザーコードのoperator newの中から、set_new_handlerが使えないではないか。

この問題に対処するため、new handlerをgetするためだけのライブラリが追加されることになった。get_new_handler()である。むしろ、今までないのが不思議だったのだが。さらに、get_unexpected()とget_terminate()も追加されるようになった。

また、set_unexpected()とset_terminate()は、nullポインターを私手はならないというルールを緩和することにした。しかしこれは、set_unexpected()とset_terminate()にnullポインターを指定するというコードの挙動を未規定(undefinedではなく、unspecified)にしてしまうのだが。

N3123: Bringing result_of near to INVOKE

result_ofの文面を、INVOKEを使って記述するようにした。

N3124: C and C++ Alignment Compatibility

alignment指定の文法を、attributeからspecifierに移す提案。これにより、alignasというキーワードが導入される。これは、specifierである。以下のように記述する予定。

alignas(16) char buffer[128] ;

N3125: Omnibus Memory Model and Atomics Paper

現在の企画の文面におけるメモリーモデルと同期処理の問題点を、ML上で議論していた。そのまとめ。

N3128: C++ Timeout Specification

clockとtimeoutの文面は、あまり宜しくない。というのも、ディレイというものが発生するからである。割り込みの間隔、関数から戻る、スレッドのスケジューリングなどのディレイを、quality of implementationと呼ぶ。また、プロセッサーやメモリーのコストを無駄に上げないためのディレイを、quality of managementと呼ぶ。とすれば、現実の環境におけるタイムアウトの実時間というものは、目的の時間 + quality of implementation + quality of managementで表されるはずである。規格でも、この概念を取り入れた文面に差し替える。

N3129: Managing C++ Associated Asynchronous State

Associated Asynchronous State周りの文面が分かりにくいので、新たなる用語を定義して、その用語を用いて文面を書き直す提案。

N3130: Lockable Requirements for C++0x

文面の細かな修正。

N3131: Compile-time rational arithmetic and overflow

Compile-time rational arithmeticが、結果は表現できるとしても、計算過程でオーバーフローを起こす場合はどうすればいいのか。たとえば、ratio_multiply<ratio<INTMAX_MAX,2>,ratio<2,INTMAX_MAX>>は、最終的に、ratio<1,1>と計算される。しかし、その計算過程で、オーバーフローを起こす。

提案は、以下の通りである。最終的な結果が表現可能であれば、合法である。実装は他のアルゴリズムを使うことによって、オーバーフローを回避することが推奨される。

N3132: Mathematizing C++ Concurrency: The Post-Rapperswil Model

この論文はすごい。すごいが、私はこの内容を理解出来ない。さしずめ、毎回髪型とヒゲが別人のように変わる、くらいおらいと (Cryolite)さん辺りなら泣いて喜ぶのではなかろうか。

内容は、FCDにおいて合意されたC++のメモリーモデルを、数学的に記述し、さらに、英語による対訳をつけたものである。

N3136: Coherence Requirements Detailed

Coherence Requirementsの追加。

C and C++ Liaison: Compatibility for Atomics

C言語とC++との間のatomicの互換性の比較。

現行のtemplate aliasの問題

現行ドラフトのtemplate aliasの定義には穴がある。現行の規格を真面目に解釈すると、以下のような記述が可能である。

template < typename T > A = int ;
A<int> a ; // int
A<double> b ; // int

template < typename T > B = struct S { T value ; } ;

B<int> c ; // S::Tはint
B<double> d ; // ODR違反?

Aは、どんなテンプレート実引数を渡そうと、int型になってしまう。Bは、クラスS自体はテンプレート化されていないのに、なぜかTが依存名である。dを定義した時点で、複数のSの定義があることになる。これはODRに違反する。

これはどう考えても望ましくないので、この穴を塞ごうというコメントが出ている。おそらくは、この問題は、次のドラフトまでに修正されるであろう。

なかなか面白かったので取り上げた次第。

2010-08-28

リファレンスに対するリファレンス

リファレンスに対するリファレンスは存在しない。

typedef int & & type ; // エラー

しかし、typedef、テンプレート仮引数、decltype指定子の型が、リファレンス型であった場合、さらにリファレンスの宣言子を書く事はできる。その場合、非常に奇妙なことが起こる。

typedef、テンプレート仮引数、decltype指定子の型を、Tへのリファレンス型とする。ここでいうリファレンスとは、lvalueリファレンスとrvalueリファレンスの両方を含む。もし、これらの型に対する、lvalueリファレンスを宣言しようとした場合、元の型のリファレンスの如何に関わらず、lvalueリファレンスとなる。rvalueリファレンスの場合、元の型のリファレンスになる。

int main()
{
    typedef int & lvalue_ref ; // lvalueリファレンス
    typedef int && rvalue_ref ; // rvalueリファレンス

    // lvalueリファレンスを宣言しようとした場合
    // 元のリファレンス型が、lvalueリファレンスでもrvalueリファレンスでも、lvalueリファレンスになる
    typedef lvalue_ref & type1 ; // int &
    typedef rvalue_ref & type2 ; // int &

    // rvalueリファレンスを宣言しようとした場合
    // 元のリファレンス型になる
    typedef lvalue_ref && type3 ; // int &
    typedef rvalue_ref && type4 ; // int &&
}

rvalueリファレンスは無視されるという、この仕様は、std::forwardを実装する上で、非常に重要である。

2010-08-27

H.264の特許利用料、緩和さる

MPEG LA - The Standard for Standards - Media

MPEG LA’s AVC License Will Not Charge Royalties for Internet Video that is Free to End Users through Life of License

エンドユーザーに対し無料で提供されるインターネット上の動画に対しては、MPEG LAの持つ特許利用料を要求しない。

どうも分かりにくい文面だ。「エンドユーザーに対して無料」という文面である。たとえば、YouTubeは基本的に、エンドユーザーから直接に金を取ることはない。しかし、広告を表示することによって、エンドユーザーに対して、広告をみなければならないという負担を課しているし、それによって金銭的な利益を得ている。しかし、この文面を文字通り受け取るならば、エンドユーザーに対しては無料であるので、おそらく特許利用料は払わなくてもいいのだろう。

では、YouTubeが選択性の課金サービスを始めて、課金ユーザーに対し、何か差別的な(例えばダウンロード速度とか画質とかの)、付加的なサービスを提供した場合、これはどうなるのか。思うに、課金ユーザーの分だけ、特許利用料を払わなければならないのだろう。

ご存知の通り、H.264のライセンス料というのは、利用数あたりの従量課税である。

そして思うに、おそらく、ブラウザー自体は、この条件には当てはまらないのではないかと思う。結局、フォーマット論争はまだまだ続くわけだ。

しかしもし、インターネットの動画を提供するWebサイトが、H.264のデコード(あるいはエンコードをも)をするブラウザー用のプラグインを、エンドユーザーに提供した場合。そして、Webサイトを利用するには、そのプラグインの利用が必須である場合、これはどうなるのか。

思うに、この緩和は、H.264ストリーム、すなわち動画に対する緩和であって、エンコーダー、デコーダーは、また別であると思われる。したがって、Webサイトは、プラグインを配布した数に応じて、MPEG LAとライセンス契約を結ばなければならないものと思われる。

2010-08-26

耳袋

1824年生まれの人が、記録の上では生存しているらしい。歴史的に、日本は国民を相当に記録している。それがたまに、こういった面白いことにもなるのだろう。

ところで、私は「耳袋」という本を持っている。この本は、ちょうど1800年前後に、当時の筆まめな奉行によって書かれた説話集である。私の持っている岩波文庫の本は、第二版である。初版発行が1939年で、その翌年に発行されたものである。この本は、私より長生きしているわけである。もっとも、私の本棚には、私より若い本というのは、めったに無いわけなのだが。

この岩波文庫には、柳田國男も編者を努めており、序を書いている。最初、何か馴染みのある文だと思いながら序を読んでいたら、最後に柳田國男の名前が記してあり、合点した。

序では、「耳袋が書かれてから約120年たっていて、現代人には読みづらくなっている」と書いている。今では、200年近くたっているわけだ。

また、言文一致という観点からみれば、当時より、1939年の方が退歩しているという。もちろん、耳袋の文章はまったくの口語というわけではないが、当時、改まって物を言う時は、こんな話し方をしていたと柳田國男は言っている。

私は幸いにして、読解力に恵まれているのか、耳袋の文章は普通に読める。もっとも、岩波文庫では、いくつかの漢字をひらがなにしている。たとえば、(など)とか、(あっぱれ)とか、與風(ふと)の類だ。そういえば、柳田國男の文章も、現代人には読みづらくなっているらしい。不思議なことだ。柳田國男など、つい先日まで生きていたではないか。

日本の参考書には図表が多すぎではないか

私は、ここ五年ぐらい、日本語で書かれたプログラミングの参考書を読んでいない。というのも、日本語で書かれた参考書の質が非常に悪いため、もとより読む気にならないのだ。

ところで、今ふと翻訳ではない日本語の参考書を眺めてみたところ、いずれも図や表がやたらと多いということに気がついた。どう考えても多すぎである。本の半分以上は図表で占められているのではないかと思うぐらいだ。何故こんなに多いのか。

私は、図表が嫌いである。思うに、図表というのは、物事を視野の範囲に収まるぐらいに見せかけるだけであり、実際に物事を理解できるわけではない。物事を明確に説明するには、文章による記述が必要である。

もちろん、機械の操作方法の説明で、ある場所に位置するボタンを押すという説明の場合には、機械の絵や写真があれば分かりやすいとは思う。しかし、プログラミング言語の場合、「機械の絵や写真」に該当するものは、ソースコードである。絵ではない。

いわゆる状態遷移の図を本に載せる場合、さらにひどくなる傾向が見られる。ほとんど一本道なはずのフローを、紙面のスペースの都合上なのかどうかは知らないが、スゴロクのようにねじ曲げているのだ。これでは分かるものも分からない。

英語の参考書を読んでいて、こんなに図表に出くわした覚えはない。とすると、世に翻訳の参考書がもてはやされるのも、畢竟、図表が少ないからではないだろうか。日本の参考書はどうなっているのだろう。

日本の参考書は、何でもやたらと図表にしたがる。「変数」という概念を説明するのに、値を入れる箱のような図を描くし、何か列挙する必要のある概念を説明するには、縦にも横にもやたらと項目の多い表を描く。それで分かりやすくなったかといえば、ちっとも分かりやすくなっていない。本末転倒も甚だしい。

さらによく分からないことに、日本の参考書は、ただそこにわずかな余白があるという理由だけで、何の意味もない、関連性に乏しいアイコン的なイラストを挿入したがる。これも意味が分からない。これは絵本でもなければ小説でもない。参考書である。技術書である。教科書である。ただスペースが余っているというだけで、無駄な芸術性を発揮されてはたまったものではない。

これは一体どうなっているのだろう。マンガの国、日本の人は、どんなに複雑な図表でも理解できるが文盲だとでもいうのだろうか。

2010-08-25

declaratorの説明しにくさ

declaratorが説明しづらい。specifierは簡単だ。基本的にキーワードか識別子だからだ。しかし、declaratorというのは、非常に面倒だ。しかも、declaratorの意味は、specifierに依存する。

int name ;

とあれば、nameはint型の変数の宣言と定義である。しかし、もし、

extern int name ;

こうなっていた場合、int型の変数の宣言である。さらに、

typedef int name ;

こうなっていた場合、nameはtypedef-nameということになってしまう。

さらに、ポインターやリファレンス、配列、関数までもが、全く別の見た目だが、同じくdeclaratorの中に入っている。

これをなんとかうまく説明しなければならない。さもなくば、specifierとdeclaratorを明確に分けて解説することはできない。

変数や関数を分けて解説するより、規格通りにspecifierとdeclaratorとして解説したほうが、C++の根本的な理解は深まるのだが、さてどうやって分かるように説明したものか。

C++におけるoverloadとoverrideとhiding

2chのC++相談室で、色々と議論が巻き起こっているようだ。少なくとも一人は、規格を参照しているようである。C++の規格上の、overloadとoverrideとhidingについて、分かりやすくまとめてみた。オーバーロードとオーバーライドは、単に音訳した際に、日本人にとって音が非常に似ているという問題に過ぎないのだが。

同じ名前で、他のシグネチャの違う関数セットのことを、関数のオーバーロード(overload)という。

void f(int) ;
void f(double) ;

この例では、void f(int)とvoid f(double)は、オーバーロードされた関数のセットである。

Derived classがBase classと同じvirtual関数を宣言しているとき、Derived classのvirtual関数は、Base classの同virtual関数を、オーバーライド(override)しているという。

struct Base
{
    virtual void f() {}
} ;

struct Derived : Base
{
    virtual void f() {}// override
} ;

Derived classのメンバー名に対し、同名のBase classのメンバーがある場合、Derived classのメンバーは、Base classのメンバーを隠している(hiding)という。

struct Base
{
    void f(int) ;
    int value ;
} ;

struct Derived : Base
{
    void f(double) ;
    double value ;
} ;

int main()
{
    Derived d ;

    d.f(0) ; // void Derived::f(dobule)を呼ぶ
    d.value ; // double Derived::valueである
}

結局これは、Derived classスコープのメンバーである名前が、Base classスコープのメンバーの名前を隠しているに過ぎない。同じことは、クラス以外のスコープでも起こる。

int value ; // グローバルスコープの変数

void f()
{// 関数fのブロックスコープ
    int value ; // ::valueを隠す。
    value ; // ローカル変数のvalue
}

virtual関数はoverrideするものである。Derived classの非virtualなメンバー関数に対し、同名のBase classの非virtualなメンバー関数がある場合、それは単に、名前を隠しているだけである。

今執筆中のC++本では、これらの用語は正しく使うつもりだが、ことさらに用語を解説したりはしない。ただし、どうも「引数」という言葉は、parameter(仮引数)とargument(実引数)をそこまで厳密に区別しなくても、問題のない場合が多いので、単に引数とだけ書いている箇所が多数ある。最初は厳密に書き分けようとしたが、すぐに、意味のないことだと気がついた。そこまで厳密に知りたければ、最初から規格を読むべきなのだ。

今昔物語集の巻十一から巻十七

ここしばらく、declaratorにたいする分かりやすい説明が書けず、C++本の執筆が滞っている。気分転換に、この数日で今昔物語集の巻十一から巻十七までを読んでいた。岩波の日本古典文学大系の今昔物語集三の範囲である。内容は、本朝付仏法である。天竺、震旦ときて、ようやく本朝に入った。

まずは、日本に仏教が入ってきた初期の段階での説話がある。これは、なかなか面白い話が多い。

ところが、続く巻は、あまり面白くない。数多くの話があるが、お互いに似通った話が多いのだ。どの話も、主語は、「法華経を持せる人」とか、「佛、観音、菩薩の助けを蒙りたる人」であり、目的語は、「難を逃れたる」、「活るを得たる」、「便を得たる」、などである。また、往生譚も多い。

これらの話は、ほとんど同じ話で、読んでいても飽きてくる。それに、ほとんどが他の書物から引いてきただけの話で、霊異記を読んでいる身としては、目新しい話がない。それでも、巻十七には、興味深い話も多かった。興味深い話に限って、典拠が判明していないのである。だからこそ面白いのだろうが。

また、強引に仏教と関連付けているが、どうもおかしい話も多い。素直に解釈すると、話の中の主人公は、嘘を付いていて、実は極悪人なのではないかという話も多く見られる。

例えば、巻十七 籠鞍馬寺遁羅刹鬼難僧語 第卅三だ。私の解釈では、以下のような話になってしまう。

今は昔、一人の僧が、鞍馬寺にこもって修行をしていた。ある寒い夜のことであった。僧は薪を集めて火をつけ、暖を取っていた。とそこへ、一人の寒さに震えた女人があらわれ、焚き火の前に座った。得体のしれぬ気味の悪い女である。とはいえ、何しろ、今は昔の話である。浮浪者の一人や二人いてもおかしくはない。ましてや、ここは京に近い寺である。寺の周りには、いわゆる正式な僧ではない、寺の奴婢として日夜にこき使われる聖や、寺をアテにした乞食の類が、相当うろついていたはずである。この女も、所詮はそういう乞食であろう。

ところが、この修業の僧は、女人を不気味に思ったのであろう。金剛杖の先を火で熱して、女の胸を強く突いた。もちろん、こんなことをされれば、だれだって激怒するに決まっている。女は当然の如く激怒し、修行の僧の頭を張り倒した。そこで僧も、金剛杖をさんざんに振り回したのである。

さて、夜が明けてみれば、そこには、青あざ傷だらけになった僧と、言われなく杖で散々に打ちのめされて死んだ女とがあった。これはまずい。僧の身でありながら、無慚破戒にも殺人を犯したわけだ。これが世に知れ渡れば、檀越はいなくなるであろうし、僧の位は取り上げられ、還俗させられてしまうだろう。たちまちに僧は一計を案じた。すなわち、つくり話をこしらえたのである。

「昨夜、鞍馬寺で焚き火をしていたところ、鬼が女の形となって現れた。まさに大口を開けて我を飲み込もうとした。もはや助からぬ。『毘沙門天、我を助け給え』と念じたところ、たちまちに朽木倒れて、この鬼を打ち殺したのだ。」と。

その後、その僧は、そそくさの他の所に逃げ去ったという。この僧の嘘が一人歩きした結果、今昔物語集の説話となったのであった。

実は、この次の、僧、依毘沙門助令産金得便語 第卅四も、だいぶ怪しい話である。黄金を得たというのは、じつはこの僧がひそかに母子を人に売って、それで得たのではなかろうか。また、この話には、なかなか興味深い部分もある。「然れば、本は黄金(キガネ)と云けるに、其より後、子金(コガネ)とは云にや有らむ」という部分である。どうも、この手のこじつけに似た由来譚は、山姥の血で蕎麦の根は赤いだとか、フルヤノモリのせいで猿のしっぽは短いなどという話と似ている。

2010-08-23

ゲームを憂う

聞説、近々発売されるというポケモンシリーズの新しいゲームは、予約だけですでにミリオンに達しているという。

史上最速ミリオン達成――「ポケットモンスターブラック・ホワイト」予約だけで100万本突破 - ITmedia Gamez

私はこの事態を非常に憂うものである。何となれば、まだ実際にどのようなものか分からないゲームを、百万人もの人間が欲しがっているということである。尋常ではない。

無論、何も分からないというのは当たらない。実際には、我々は皆、よく分かっているのである。このゲームはおそらく確実に、過去のシリーズの仕組みを踏襲したものである。しかし、そういうゲームは、すでにたくさん出ている。なんでまた車輪の再発明をしたようなゲームが必要なのか。

このように、消費者が続編ばかりを買うようになると、新しいゲームが出てこなくなる。すべて、過去の作品の移植に、申し訳程度に毛を生やしたものになってしまう。全くもってつまらない世の中だ。

開発費が高騰している。新しいハードに見合った新機能を実装しなければならない。それはそうかもしれぬ。しかし、結果としてゲームが面白くなっていなければ、そんなものには意味がないと言わざるをえない。

ゲームは、全然面白くなっていない。それどころか、ますますつまらなくなっている。スプライトが横一直線に何個までという制限などなくなったのに、最大何和音という制限が、かなり緩和されたというのに、アセンブリで書かなくてもよくなったのに、ゲームはちっとも面白くなっていない。

それどころか、むしろ悪くなっているのである。コントローラーからの入力への応答速度は、極端に悪くなった。パイプライン化されたGPUと液晶により、描画にも遅延が入った。Now Loadingは言うまでもない。もちろん、最近のゲームは、描画内容への数百ミリ秒以内の反応だとか、ボタンの連打速度だとか、いかに正確に短時間でキーシーケンスを入力するか、等という事に重きをおいていない。とはいえ、さすがに行き過ぎであると思う。

ゲームの本質はなんだろう。

SophieHoulden.com - The Linear RPG
Achievement Unlocked | Armor Games

2010-08-21

日本のプログラマー人口は何人ぐらいだろう

一体、日本にプログラマーは何人ぐらいいるのだろうかということを、ふと疑問に思った。まあ、信頼できる答えなど出せるわけがないのだが、どのくらいいるのだろうか。

あまりいないんじゃないかなというのが私の意見だ。百万人いるかどうかも怪しい。根拠はない。

2010-08-20

今日読んだ面白い文章

できれば所在不明のままでいてほしい:日経ビジネスオンライン

最近どうも、名文だと思える文章に出会っていない。また、ネット上にも、さほど面白いネタがない。毎日、規格書を睨んで、執筆を続けている。最近の娯楽は、専ら今昔物語集だ。とすると、必然的に、ブログの執筆が滞る。

しかし、このややまつろわぬ印象のある文章は、なかなか面白い。

2010-08-14

後の世では、何とでも言える

人生を書き換える者すらいた。: C++は何を間違えたのか

ムーブコンストラクタなぞとても使いこなせる自信がない。

ムーブの概念とC++の型システムの詳細が分からないユーザーは、別にムーブを使う必要はない。ムーブはライブラリ実装者のための機能である。なぜなら、明示的に使わなくても、関数の戻り値などのrvalueは、勝手にムーブされるからだ。

これが方向性の歴史的誤りだったよな。
 C++はこういうのではなく、2パスコンパイルにしてヘッダファイルを不要にしたり、GCを言語レベルでサポートしたりすれば今頃の情勢は違うものになったかもしれないのに、結局JavaやC#の外見的な言語仕様のベースになっただけなのはちょっとさびしい。

後の世では、何とでも言える。C++が作られた当時は、到底そんなことは現実的ではなかった。歴史の話をする。

Bjarne Stroustrupが博士号をとるべく研究していた時、彼はSimulaを使っていた。Simulaには、GCがあった。しかし問題は、Simulaの実装は遅すぎたのだ。当時はまだGCのアルゴリズムが洗練されておらず、ハードウェアも、現代では信じられないくらい遅かったからだ。したがって、GCは不可能であった。

当時のハードウェアは、実に遅かった。CPU速度、メモリ、ディスク容量と速度、あらゆるハードウェアが、絶望的に遅かった。そのようなハードウェア上でのコンパイラの実装も、当然、かなり制限を受けた。当時の多くのC言語コンパイラは、ソースコードから一文読み込み、解釈して、すぐに目的のコードを生成し、さてまた次の文の読み込みをしたものである。前後の文脈を考慮した上での最適化など、望むべくもない。C++がregisiterやinlineといった機能を付け加えたのにも、理由があったのだ。

そのような状況であったから、単なるテキストを、その場に流しこむという、愚直な#includeの機能は、実に効率的な方法だったのだ。果たして、当時のハードウェアで、2パスコンパイルして、ソースコードに必要なシンボルテーブルをメモリ上に保持できたかどうか。その辺は、あやしいものである。

この当時、C++は時代の最先端をゆく理想主義な言語であった。もちろん、今でもだいぶ理想主義が入って入るものの、当時に比べたら、非常に現実的である。

C言語には、そもそも、関数の前方宣言などなかった。プログラマーは、特に宣言もせず外部で定義されている関数名を使った。コンパイラーは、プログラマーのコードを信用して、未知の関数を呼び出すオブジェクトコードを生成した。C++が、名前は、かならず使う前に宣言されていなければならないと決めたとき、多くのプログラマが反対した。ある者は、コンパイル時間が極端に長くなることを恐れた。またある者などは、実行時のパフォーマンスに影響が出ることをさえ、恐れた。

今、C言語の文法が、いくらかまともになっているのは、まったくC++のおかげだと言える。当時のC言語がどんな惨状であったかは、改訂されていない、当時のK&Rを読めば分かる。

後の世から、物事を批判することは簡単だが、そんなことは、当時は不可能であるし、もし、当時に現代の常識で物事を決めていれば、その仕組は、現代に残ることはなかっただろう。これはC++に限る話ではない。

例えば文字コードだ。当時は、文字コードに8ビット費やすことすら、無駄が多かったのだ。7ビット、いや、6ビットでも十分足りたのだ。とすれば、何故文字ごときに8ビットも浪費する必要があるというのか。

一文字に8ビットは贅沢すぎるという話を、現代において行えば、世の笑いとなるであろう。しかし、当時としては、切実な問題だったのだ。

PCの掃除

今朝、非常に過ごしやすい気候だったので、クーラーを付けなかった。しかし、やけにPCのファンが回る。気になってCPUの温度を調べたところ、ほとんどアイドル状態なのにも関わらず、何と78度であった。GPUやHDDも軒並み高い温度を示している。これはまずい。すぐさま電源を落とし、ケースを開ける。案の定、ホコリが溜まっていた。無理もない、今年はPCのケースを開けた覚えが無いのだから。眼に見えるものだけピンセットで取り除くと、CPU温度が15度さがった。

しかし、このままではまずい。GPUや電源ファンなどにも、埃が溜まっている。急遽エアダスターを買ってきて、一時間ほどかけて、埃を取り除いた。その結果、非常に快適に動作するようになった。アイドル状態で55度、x264のエンコードでベンチをとっても、66度以上には上がらない。まだ少し高い。いずれ、ファンとヒートシンクを取り除いて掃除し、新しいシリコングリースを塗ったほうがいいのだろうが、とりあえずは、問題を解決できた。

ところで、Intelの文書によると、私の使っているQ6600の最高動作温度は、71℃とある。かなり危ないところだったらしい。気がついてよかった。

教訓として、クリーンルームの中にいるのでもない限り、PCケースはこまめに開けて、ホコリを掃除するべきである。

お前にSunが救えるか?

お前にSunが救えるか?

Oracle、「分からぬ、だが特許ゴロにはなれる」

Oracle(Sun Microsystemsを買収)は何がしたいんだろう。結局、Sunの実装がAndroidに勝てなかったというだけじゃないか。自分の粗悪な製品を棚にあげて、特許訴訟を起こす。愚かなことこれに過ぎたるはない。旧Sunの社員の多くがGoogleに引きぬかれていったのも、当然というわけだ。

ともかく、これで、Oracleはモバイル市場を完全に敵に回したわけだ。もう立つ瀬はない。

しかし、Javaはよく分からない。Microsoftが独自のJavaVMを開発したとき、Sunは訴訟を起こした。そこでMSは、独自のJavaVMを取り下げた。結局MSは、本来Javaが占めるべきだった場所の大半を、C#に置き換えてしまった。Sunが馬鹿なことをしたせいで、本来労せずして得べかりしユーザーを失ったわけだ。今回も、同じことになるだろう。もしOracleが訴訟に勝てば、携帯の共通プラットフォームとしてのJavaはなくなる。負けたとしても、もはやOracleが市場に入り込む余地はないだろう。

プログラミング言語の規格や実装の権利が、特定の個人や団体の意のままになるというのは、悲惨である。C++の標準化の際には、この問題を避けることに多大な努力を払った。もし当時、AT&TやBjarne Stroustrupなどが、C++の権利を主張していたら、今日のC++の興隆はなかっただろう。なぜならば、ある特定の個人や企業の意のままに変更が行われるような言語など、誰も使いたがらないからだ。

まあ、Javaというのは、言語自体が貧弱だから、その思想も自ずから貧弱となるのであろう。

日本のソフトウェア業界に未来はあるのか

システムエンジニア 生き残りの極意: 実はオブジェクト指向ってしっくりこないんです!
Togetter - 「派遣PG時代の思い出」

なんで日本の業界はこんなことになっているのか。真面目にプログラマの仕事を探していたとき、受ける会社すべて、面接の時点で明らかに危険な電波を発していた。「関数を分けず、main関数に全部かけば一番速いでしょ」と真顔で言い切った面接官が存在した。やんぬるかな。

2010-08-12

原文Bjarne Stroustrupへのインタビュー

新しいプログラミング雑誌、プログラミングの魔導書 vol.1では、C++の設計者にして最初の実装者であるBjarne Stroustrupへインタビューを行った。インタビューは、英語が使われた。その英語は、日本語に翻訳されて、雑誌に載せ、すでに発行されている。

しかし、翻訳というものを信用していない人もいるだろう。第一、ほかならぬ私自身でさえ、翻訳は嫌いなのだ。このたび、Bjarne Stroustrupが、自信のWebサイトで、原文を公開した。以下で落として読むことができる。

Stroustrup: Interviews

Interview by Royo Ezoe C++0x from now to the release of the Standard for a new Japanese mazagine called Programmers' Grimoire. April 2010.

インタビューの他でも、色々と興味深い問答があったのだが、すべてを載せることはできなかった。たとえば、Bjarne Stroustrupの原文では、以下のようなやり取りが付け加えられている。

(C++をどうやって教育すべきかという質問への追加、サブセット規格よりコーディング規約という返答に対して)

質問:

サブセット規格よりコーディング規約といいますが、テンプレートのないサブセット規格と、テンプレートの使用を禁止しているコーディング規約は、全く同じものではないでしょうか。技術上の理由は全くないにも関わらず、テンプレートやSTLやBoostの使用を禁止しているコーディング規約を強いられている人の話も聞きます。

Bjarne Stroustrupの返答:

コーディング規約は、明確に定義された、対象とするアプリケーションやその分野にあわせて設計されるべきである。さもなくば、問題を引き起こす。コーディング規約というものが、C++の経験が浅い者によって作られることも、実に多い。特に、ある団体の開発言語が、別言語からC++に移った場合によく起こることだ。わたしはかつて、まだC++でまともにプログラミングしたことのない者が、コーディング規約を書くという例をなんども見てきた。そういう場合、人は大抵、かつて自分が使っていた別言語にはない機能を禁止しようとしたり、別言語に存在する問題を防ぐためのルールを、C++にも当てはめようとする。これは、実にC++の利用に取って害悪である。たとえば、C畑からやってきた者は、関数のオーバーロードを極度に恐れるあまり、禁止する。その結果、彼らは問題の多いマクロを多用して、ジェネリックプログラミングのマネ事を行うのだ。実に非生産的である。他には、コンストラクターで、「複雑なこと」をするのを禁止したりする。その結果、不必要に問題の多い、二段階の初期化と、例外の誤用をするのだ。結果のC++コードは、まともなC++プログラマーによって書かれたようには見えん。C++でハンガリアン記法を使うというのも、明白に間違っている。

そもそも、良いコーディング規約というのは、禁止事項のリストではないのだ。よいコーディング規約は、言語の有効な使い方を示すべきなのだ。思うに、最良の方法とは、ライブラリを使うことによって、問題の多い非生産的な言語の使用を避けるべきなのだ。私が考案した、JSF++の基本的な考え方は、まず、言語をライブラリで、対象の分野に沿うように拡張しておいて(訳注:つまり、ライブラリの実装自体には制限を設けない)、それから(訳注:ライブラリを実装した後で)、ライブラリを効率的に使えるように、言語のサブセットを定義するのだ。このようにすれば、単に「言語のサブセット」より遥かに単純で安全な規約を作ることができる。例えば、JSF++は、ポインター変換や、ポインターと配列の関係、配列のオーバーフローの問題を、たったひとつのルールで解決している。インターフェースに配列を使うな(つまり、関数の実引数として)。データの集合を渡すには、何種類かの単純なコンテナを用意する。このコンテナは、安全ではない暗黙的な型変換を行わず、要素の数を把握している。MISRAのような、ポインターを安全に使えるようにする、などといったコーディング規約は、それ自体は何らプログラマの生産性に寄与しない、何十ものルールを付け加えなければならん。それでも、やはり問題は起こるのだ。このような問題は、愚直に言語を限定するというアプローチから生まれるのだろう。プログラマーに、言語自体の問題に対処させながら、しかも、その問題に対処するための、言語側で提供されている機能を使わせないというのだ。これをC++のサブセットに当てはめると、プログラマーは、高級なアブストラクション機能(クラスやテンプレート)を使えず、低級な言語機能(ポインターやキャスト)で対処しなければならないということになる。これは問題が多いし、非生産的である。

単なる言語のサブセットと、コーディング規約によって定められているサブセットの根本的な違いとは、完全なISO C++が、コーディング規約の実装者には提供されているということだ。よいコーディング規約とは、スーパーセットのサブセットであるべきだ。このスーパーセットというのは、C++と、対象の環境用のライブラリのことだ

テンプレートは、C++の型安全と効率のための根本的な機能だ。例えば、たったひとつの要素型しか使わない場合を除いて、コンテナが必要であるし、型安全で効率的なコンテナを実装するには、テンプレートが必要になる。組み込みの配列は、型安全なコンテナに比べたら、実に貧弱な選択肢だ。テンプレートの多くの機能(訳注:テンプレートの全機能ではない)をコーダーには禁止するコーディング規約はあったとしても、ライブラリを構築するためにも禁止しているような規約は、良い規約ではない。しかしだ。コーダーに、テンプレートの使用自体をまったく禁止するのがふさわしいような場面というのは、考えられん。とはいえ、すべてのコーディング規約は、テンプレートの利用を、その目的の分野にふさわしいように、制限をしてはいるだろう。

このほかは、雑誌で翻訳しているので、買って読んで欲しい。

ルービックキューブの神の数字、解かれる

ルービックキューブを、あらゆる状態から最小手で解くには、一体何手必要か。この最小手を得るアルゴリズムを、「神のアルゴリズム」といい、このアルゴリズムが弾きだす最大の手数を、「神の数字」と呼ぶ。神の数字はいくつかであるかということは、これまで研究者を魅了させてきた。

ルービックキューブの多くの状態は、神のアルゴリズムを使えば、15手から18手で解ける。このことから、明確な証明はないものの、神の数字は18手以上であるといわれてきた。しかし、20手未満ではどうしても解けぬ状態が発見されたので、18手であるとする説は否定された。では何手か。これまでも、25手以下であるとか、23手以下である、いや22手まで削減できた、などという証明がされてきたが、このたび、神の数字を弾きだすことに成功した。

証明は、コンピューターを使ってすべての組み合わせを検証するという総当り的な手法で行われた。組み合わせの数は、「絶望的に多かった」ため、低減する努力が試みられた。重複やほとんど似た状態を省き、約二千万にまで組み合わせを削減することに成功した。

ひとつの組み合わせを検証するのに、高性能なPCで20秒から30秒ほどかかる。研究者たちは、スーパーコンピューターを借りて計算させようと考えた。ところが、ここに意外な者からの協力が得られた。Googleである。Googleが計算をしようと申し出たのであった。

「我々は、未だGoogleがどのような電算機を用いて計算を成し遂げたのかを知らず」と研究者は語る。

計算はなされた。もっとも、この二千万の組み合わせからは漏れた例外的な組み合わせが、まだいくつか残っていたので、それはもっと遅い、通常のデスクトップ機で計算しなければならなかったが、ともかく、計算はなされた。神の数字は、20手であった。

「なんだか、原点に戻ってきたんだという感じがします」と研究者は言う。「ルービックキューブは80年代を象徴する存在であり、私が数学という学問の道に入った理由でした」と。

しかし、ルービックキューブへの研究は、これもって終わるものではない。今回解いたのは、3x3x3のルービックキューブである。研究チームは、これから4x4x4のルービックキューブへの研究に着手するという。

参考文献:
God's Number is 20
God's algorithm - Wikipedia, the free encyclopedia
BBC News - Rubik's Cube quest for speedy solution comes to an end

2010-08-11

下鴨納涼古本まつりをみてきた

下鴨納涼古本まつりをみてきた。予想に反して、かなり多くの古本屋が集まっている。一通り見てまわるだけでも、だいぶ時間がかかる。

あまり面白そうな本はなかった。もちろん、荻生徂徠とか本居宣長などの本は、なかなか興味深いが、いかんせん値段が高い。だいぶくたびれた岩波の耳袋が捨て値で売られていたので、これを買ってきた。

これまただいぶ状態の悪い有朋堂の宇津保物語が捨て値で得られていたが、買うかどうか迷った。無論、源氏物語と宇津保物語は、いずれ読まなければならない文章だとは思う。しかし、どうもかな文字というのは好かない。本居宣長の文章も、正直やりすぎとしか思えない。

Bloggerに新しいコメントシステムが来る

Blogger Buzz: New Comments System on Blogger

変更は順次適用されるとのことで、まだ全アカウントでは使えないのだが、新しいコメントシステムが入るようだ。

全コメントを管理できるInboxと、スパムフィルター。

2010-08-10

チャガガなんちゃら池

Don't Fuck With Me Google

さすがGoogleというべきか。

Lake Chaubunagungamaug - Wikipedia, the free encyclopedia

この池は、かなり多くの表記法があり、Chaubunagungamaugの他にも、Chargoggaggoggmancogmanhoggagoggとか、Chaubunagungmamgnamauggとか、Chargoggagoggmanchoggagoggなどとも呼ばれているが、中でも、Chargoggagoggmanchauggagoggchaubunagungamauggや、Chargoggagoggmanchauggauggagogogchaubunagungamauggは、かなり長い名前として知られている。

関連:Eyjafjallajökull火山の近くにある都市の名前を答えよ

YouTube - Monty Python's - Johann Gambolputty

using declarationの妙義

using declarationは、宣言されている場所から見える名前しか、宣言場所のスコープに導入しない。

namespace NS { void f( int ) { } }

// NS::f(int)をグローバル名前空間に導入する
// NS::f(double)は、ここでは、まだ宣言されていない
using NS::f ;

namespace NS { void f( double ) { } } 

int main()
{
    // NS::f(int)を呼ぶ
    // NS::f(double)という名前は、この場所からは名前探索されない。
    f( 0.0 ) ;

    // NS::f(double)をmain関数のブロックスコープに導入する
    using NS::f ; 

    // ここでは、NS::f(double)が名前探索できる
    // オーバーロード解決により、NS::f(double)を呼ぶ
    f( 0.0 ) ;
}

宣言なしに名前を使うことはできないというのは、C++の原則である。しかし、これはなかなか面白い仕様だ。

2010-08-08

プログラミングの魔導書 Vol. 1のレビュー

株式会社ロングゲート - 製品案内

プログラミング雑誌が正式に公開されたので、レビューでもする。ただし、私は常に、何事にも批判的な目を向けているので、自然とレビューも、辛口になってしまう。

Bjarne Stroustrupへのインタビュー 著者:本人

私が書いた。タイトル通り、C++の設計者にして最初の実装者であるBjarne Stroustrupへのインタビュー。C++0xについてと、C++の教育について論じている。

boost::serializationの紹介 前編 著者:近藤 貴俊

これもタイトル通り、Boost.Serializationの入門。

Variadic Templates お前を待っていた 著者:Egtra

Variadic Templatesを使って、Win32 APIのEnum系のAPIのラッパーを作る。あまり宜しくない。まあ、斬新な実装だとは思うけどさ。Variadic Templateをユーザーが直接使う必要はないだろ。それに、記事では結局、Enum系APIをそれぞれ個別にラップしていることには変わりないわけだ。じゃあ、これでいいじゃないか。

namespace Ezoe
{
    namespace detail
    {
        BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
        {
            auto func = *reinterpret_cast< std::function< bool (HWND) > * >( lParam ) ;
            return BOOL( func( hwnd ) ) ;
        }
    }

    bool EnumWindows( std::function< bool (HWND) > proc )
    {
        return bool( ::EnumWindows( &detail::EnumWindowsProc, reinterpret_cast<LPARAM>(&proc) ) ) ;
    }
}

使い方

// std::coutに流しこむ
void f()
{
    Ezoe::EnumWindows(
        []( HWND hwnd ) -> bool
        {
            std::vector<char> buf( ::GetWindowTextLengthA(hwnd) + 1 ) ;
            if ( ::GetWindowTextA(hwnd, &buf[0], buf.size()) > 0 )
            { std::cout << &buf[0] << std::endl ; }

            return true ;
        }
    ) ;
}

// std::wstringのstd::vectorに流しこむ
void g()
{
    std::vector< std::wstring > v ;
    Ezoe::EnumWindows(
        [&]( HWND hwnd ) -> bool
        {
            std::vector<wchar_t> buf( ::GetWindowTextLengthW(hwnd) + 1 ) ;
            if ( ::GetWindowTextW( hwnd, &buf[0], buf.size() ) > 0 )
            { v.push_back( std::wstring(&buf[0]) ) ; }

            return true ;
        }
    ) ;
}

Variadic Templatesは、確かにすばらしい。しかし、Joe Coderが使う必要はない。結局、この記事が何をしているかというと、劣化std::functionの実装なのだ。だったら最初から、std::functionを使えばいいのだ。Variadic Templatesは、いうなればアセンブリ言語である。アセンブリ言語はプロでなければ使えないように、Variadic Templatesも、プロが使うべきなのだ。それに、結局Boost.Fusionを使っているのであれば、Variadic Templatesを使う意味がそれほどあるとも思えない。他人の書いたマクロに頼って、マクロアセンブラーでアセンブリを書くようなものである。なおさら自分でVariadic Templatesを使う意味がない。Variadic Templatesは、std::fucntionを実装するためにあるのだ。

私の実装では、コールバック関数として、std::functionが渡せる。シグネチャは、引数からLPARAMを取り除いた形だ。コールバック関数としてstd::functionを渡せるようになれば、関数オブジェクトが渡せるというわけだから、可能性は無限だ。

Chronoライブラリで考える型システム 著者:melpon

C++の強い型システムの中で、単位を実装する話。1秒 + 1秒は、2秒になってほしい。しかし、1秒 + 1分は、61秒になって欲しい。これは、秒と分とは、時間という概念を指すのだが、単位が違うためだ。分とは、ご存知の通り、60秒のことである。

C++0xの新しいライブラリであるratioを引き合いにだしながら、単位をC++の型システムの上に落としこむ方法を論じている。

オーブンレンジクッキング 著者:高橋 晶

物事を広く浅く紹介するのは、アキラさんの十八番である。この記事では、Ovenという、変態的なライブラリについて述べている。このライブラリは、まあ、関数型言語の原理主義者には、好まれるのかもしれない。私は使いたくないが。

Hello, C++ World! 著者:稲葉 一浩

Let's Boostという、まあ、言い方は悪いが、猫でも分かる(笑)のBoost版のようなWebサイトの中の人。

単純なHello,worldプログラムに、以下にC++の複雑なしくみが潜んでいるかというお話。まあ実際、Hello,worldごときにADLを使うようなC++は、異常だと言わざるをえない。

Crawling in the Stream 著者:zak

この雑誌のイラストを描いた人。iostreamについて、型の如く説明している。まあ、iostream自体、プログラミングを勉強するときぐらいしか使わないから、あまり価値はないと思うのだが。

メタプログラミングノキワミ アッー! 著者:DigitalGhost

日本人で唯一、Boost.Preprocessorの実装を理解している人間。この記事では、一般人を対象とするため、嫌々ながらBoost.MPLを使っているが、おそらく彼の本心では、プリプロセッサーだけでやりたかったに違いない。

Boost.AsioによるHTTP通信入門 著者:clown

題名通り、Boost.Asioによるネットワークプログラミングの入門。Boost.Asioの実装はなかなかすばらしいので、是非とも使うべきだと思う。Windows環境でネットワークプログラミングをするのに、WinsockとIO completion portを直接書いたことのある身として、特にAsioを進める次第。

でも、実際に、移植を考える必要がなく、Windows環境だけでネットワークプログラミングをやれと言われたら、多分私は、Vista以降のthread poolを使って、結局IO completion portを直接使って実装するだろうと思われる。別に、IO completion portは難しくない。それよりiostreamの方が難しい。なにより、日本語がまともに使えないので、意味がない。

C++の歴史 著者:本人

私が書いた。コンセプトとしては、D&Eに載っていない、すなわち、D&E以降のC++の歴史の話である。D&Eが好きな人は、楽しめるだろう。

BoostCon2010体験記 著者:近藤 貴俊

BoostCon 2010の参加してきた近藤さんの体験談。いかにもステレオタイプな日本人っぷりをアピールし、以て外人をして日本人のイメージを一層固定化せしめることに尽力したらしい。それにしても、BoostConに参加したとはうらやましい。カネさえあれば私も行きたい。

2010-08-07

いまだに慣れない英語

"Not a native speaker of English?"(英語ネイティブか?)と聞かれて、「違うに決まってるだろ!」と言いたかったのに、自信満々に、"Of course I am!"(あたりまえだろ、俺はネイティブだよ!)と答えてしまった。英語の否定疑問文には、一生慣れる気がしない。少なくとも、ネイティブではないことを実証することに成功したわけだが。

pronounceとpronunciationのスペルをしょっちゅう間違える。どう間違えるかというと、pronunceとpronounciationだ。このスペルの違いは、実際の発音の違いを表しているのだが、文字を打つときは、必ず間違えてしまう。おそらく、私の頭に、この二つの単語の発音の違いが叩き込まれていないのが、原因だと思われる。

2010-08-06

enumのまとめ

C++0xでは、enumがだいぶ変更されている。

unscoped enumは、従来のenumだ。ただし、enum-baseが追加されている。enum-baseが指定されていない場合、内部型は実装依存である。他には、名前があるかどうかで区別する必要もある。

scoped enumは、強い型付けがされたenumだ。scoped enumには、必ず名前が必要である。enum-baseが指定されていない場合、デフォルトでintになる。

opaque-enum-declarationは、enumを定義せずに宣言するための機能だ。これには、unscoped enumの場合、enum-baseが指定されていなければならない。scoped enumの場合は、デフォルトでintなので、指定されていなくても構わない。

これを考えると、unscoped enumの名前の有無とenum-baseの有無。scoped enum。opaque-enum-declaration。合計、6種類のenumがあることになる。

enumの解説は、この種類ごとに、分けて解説していく形にしよう。

ただし、unscoped enumは、四種類もあるのが、どうにかならないものか。

ところで、私は列挙型という名称を使いたくない。enumにしようかとおもっている。

個人的には、unscoped enumを使うべきではないと思っている。しかし、整数型への暗黙の型変換が欲しい場合もあるかもしれない。単なるマジックナンバーに名前をつけたい場合があるからだ。なかなかうまくいかないものだ。もっとも、そういう場合は、名前空間スコープ内のconstな変数を使うべきだと思うのだが。

プログラミング雑誌の予約、今日まで

株式会社ロングゲート - 製品案内

物理的な紙の印刷物としてのプログラミング雑誌の予約は、8月6日までとなっている。明日以降は、PDF版ならば、買うことができる。

何事も問題がなければ、明日以降、PDFのダウンロードが出来る予定らしい。

明日以降、私の記事への感想がネット上で読めるといいのだが。

空を飛ぶ夢

夢のなかで、ふと、子供の頃はよく空を飛んだものだということを、思い出した。記憶によれば、誰でも数十メートルぐらいは飛行できたはずである。はて、本当にそうだっただろうか。

気になった私は、さっそく、「空を飛ぶ」というクエリーでググった。すると、Wikipediaにも、「人間は、滑空により、誰でも数十メートル程度、空を飛ぶことができる」とか、「空をとぶのは、主に子供である。成人が空を飛ぶには、色々と問題が多い。過去にも、住宅地で空を飛んでいた中年男が、不審者として通報された事例がある。これを是正するため、飛行普及団体と称する団体による運動が云々」などと書かれているではないか。はては、「空をよく飛ぶ有名人」などといったリストまである始末。私は、疑いようなく、人間は空を飛べる生物であると確信した。

しかし、運動不足の今でも飛べるだろうか。試しにその場でジャンプしてみたところ、十秒ほど滞空することができた。飛べる。飛べるぞ。さっそく表に出て、久しぶりに飛んでこよう。

と、ここで夢が覚めた。現実には、走り幅跳びの世界記録は、マイク・パウエルの8.95メートルである。この記録は、人間にしてはすばらしいが、残念ながら、その跳躍フォームは、飛行と呼ぶには程遠い。

2010-08-05

変更変更、また変更

現在、C++標準化委員会のrapperswil会議が行われている。どうやら、また大幅な変更がありそうだ。とくに、アトリビュート周りがかなり変更される。アトリビュートの執筆は保留したほうがよさそうだ。

また、今から該当部分を修正しなければならない変更もいくつかある。やれやれだ。

Google Waveの開発終了に思う

Official Google Blog: Update on Google Wave

当初、私はGoogle Waveに感動した。ブラウザでここまでできるとは、にわかに信じられなかった。いい時代になったものだ。

ところが、私のWave熱は、すぐに冷めてしまった。というのも、他人の書き込みがどこにあるのか分かりにくい(私はspaceというショートカットを知っているが、やはり分かりにくいことに変わりはない)

また、ソフトウェアには、パフォーマンスが重要なのだということが、嫌というほど思い知らされた。まともにタイプすらできないようなサービスを使いたいとは思わない。

そのため、私はすぐに、Google Waveをやめた。すでに、Waveにおけるコミュニケーション機能は、既存のIRCとMLに勝つことはできないし、ファイルのアップロードも、数GBの無料、有料オンラインストレージのサービスが複数がある以上、やはりWaveを使う必要はない。

Finally! My dream comes true!

YouTube - Something Extraordinarily Satisfying

これはすばらしい。長年、是非ともみたいと夢見ていた光景が、またひとつ実現した。

そういえば、今回、始めてYoutubeの新しい埋め込み方式である、HTML5のvideo要素を使った動画の埋め込みを使ってみた。この埋め込みに関して詳しくは、YouTube API Blog: A New Way To Embed YouTube Videosを参照。

2010-08-04

auto指定子の型の推定方法

autoな変数の型は、代入の式になる。そう言ってしまうのは、単なる一ユーザーである。いやしくもプログラミング言語学者(language lawyer)を自負している以上、auto指定子が、どうやって初期化子の式から、変数の型を推定するのかということを、厳密に知らなければならない。

実際、以下のコードをみれば、「変数の型は初期化の式になる」というのが、不完全な説明であるのは理解できるだろう。

    int const a = 0 ; // aの型はint const
    auto b = a ; // bの型はint
    auto const c = a ; // cの型はint const
    auto const & d = a ; // dの型はint const &

しかし、この型の推定方法は、何かに似ている。そう、まるでテンプレートの実引数の型を推定しているようだ。まさにその通りである。auto指定子によって宣言された変数の型は、初期化子の式から、テンプレートの実引数推定と同じルールを用いて、推定しているのである。

つまり、

auto const & c = a ;

上記の文における変数の型とは、

template < class U > void f( U const & u ) ;

という関数テンプレートに対し、f(a)という呼び出しをした場合に推定される、テンプレート仮引数Uの型に等しい。

ところで、ひとつだけ例外がある。auto指定子は、初期化リストも型推定できる。

auto a = { 1, 2, 3 } ; // aの型は、std::initializer_list<int>
auto b = { 1.0, 2.0, 3.0 } ; // bの型は、std::initializer_list<double>

auto c = { 1, 2.0 } ; // エラー、型が推定できない

今昔物語集の表記は笑えない

ふと何気なく、この前書いた記事を読み直したところ、「この機能は最適化の役に立たない」と書くべきところを、「この機能は最適化に役に立たない」と書いていた。もちろん、QWERTYレイアウトでは、IとOのキーは隣あっているから、単に押し間違えたのかもしれぬ。それにしても、間違いは間違いだ。

実は、今昔物語集には、間違いなのか意図的なのかは定かではないが、これと同じ表記が散見される。ニとヲが複数使ってあるのだ。最も、これは今昔物語集に限らず、伊勢物語や源氏物語にも見られるそうだから、意図的なものなのかもしれない。

ところで、今昔物語集の巻第十四 弘法大師、挑修圓僧都語 第四十は、かなり面白い。

2010-08-03

例外指定

C++には、例外指定というものがある。これは、ある関数から投げられる例外を、あらかじめ明示的に指定しようという目的で作られた。

void f() throw(int, float, std::exception) ;

ここで、もし関数fが、int, float, std::exception以外の例外を投げた場合、関数std::unexpectedが呼ばれる。つまりこれは、関数tryブロックを使って以下のように書くのに等しい。

void f()
try {
// 関数本体
}
catch( int ) { throw ; }
catch( float ) { throw ; }
catch( std::exception ){ throw ; }
catch( ... ) { std::unexpected() ; }

この機能は、それほど難しいこともない。極論で言えば、上記のように、単なるソースコードの変形でも実装できるわけだ。この機能は、あまり実装するだけの価値もなかったので、多くの現実のコンパイラでは、単にパースだけして、無視された。

よくある誤解として、この機能は最適化のためにあるという思い込みがある。実際、この機能は最適化の役に立たないばかりか、むしろ最適化の妨げになる。というのも、いくつかの実装では、tryブロックというのは、存在するだけでコストがかかる代物だからだ。現実の多くのコンパイラは、実行時のパフォーマンスを犠牲にするよりは、規格を無視する方を選んだ。

ところで、この例外指定には、思わぬおまけがあった。throw()と指定した場合、その関数は、例外を投げないことを指定することになる。これは、規格的に考えると、例外を投げた場合、std::unexpectedを呼び出すことになる。

ところで、ここにMSVCという、規格を守らないことで非常に有名なコンパイラがある。MSVCの環境では、もし、ある関数が例外を投げないということが保証されていれば、行うことのできる、ある最適化手法が存在した。そこで、MSVCは、throw()が指定されていてもstd::unexpectedを呼び出さないばかりか、関数は例外を投げないという前提のもとに、この最適化を行ったのである。これはもちろん、規格違反である。

しかし、いくら理論的に優れていても、現実にそぐわない規格などというものには意味がない。C++0x制定にあたって、むしろ、この挙動を規格で定義しようではないかという動きが起こった。その結果、例外指定は大きく変わった。

まず、従来の、投げる可能性のある例外を指定する機能は、これまでと変わらない。

throw()という記述を、例外を投げないという意味を表すものと定義した。また、このthrow()と同じ意味を持つものとして、新しいキーワード、noexceptを導入した。throw()、noexcept、noexcept(true)は、無例外指定である。

void f() ; // 無指定、任意の例外を投げる可能性がある
void f() throw() ; // 無例外指定
void f() noexcept ; // 無例外指定
void f() noexcept(true) ; // 無例外指定
void f() noexcept(false) ; // 任意の例外を投げる可能性がある

もし、無例外指定の関数が例外を外に投げた場合、関数std::terminateが呼び出される。この挙動は、少し意外かもしれない。std::unexpectedを呼び出すという仕様が、オーバーヘッドの問題で無視されていたのに、これはどういうことか。

これは、現在のコンパイラの開発者の一致した意見として、例外を投げないと指定されている関数が例外を投げた場合、std::terminateを呼び出すことには、オーバーヘッドは存在しないからである。例外を投げないと指定されている関数が、例外を投げるというのは、そもそもバグである。セキュリティ上の観点から考えても、そのような場合、プログラムは強制終了するのが望ましい。

なお、無例外指定の関数が、例外を投げる場合、コンパイルエラーになるかどうかは、未規定である。というのも、すべての例をコンパイル時に検出するなどは、どだい無理だからだ。無例外指定の関数の内部で例外を使うのは、自由である。無例外の意味は、関数の外に例外を投げないということである。

// この関数は外に例外を投げる。
// コンパイルエラーになるべき
void f() noexcept
{
    throw 0 ;
}

// この関数は、絶対に外に例外を投げない
void f() noexcept
try {
    throw 0 ;
} catch( int ) {}

この例は、比較的簡単に思われる。では、以下の例はどうか。

void f() noexcept
try {
    throw 0 ;
}
catch( int )
{
    if ( rand()%2 ) throw ;
}

この場合、関数fが例外を投げるかどうかは、関数randの戻り値にかかっている。残念ながら、randの戻り値は、実行時にしか分からない。タイムマシーンを発明しない限り、コンパイル時エラーなどというものは、無理である。

このため、無例外指定が外に例外を投げる場合、コンパイルエラーになるという保証はない。もちろん、コンパイル時に判定できる場合、コンパイルエラーにしてもよい。規格はそのことを制限してはいない。

ちなみに、あるexpressionが例外を投げる可能性があるかどうかをコンパイル時に判定するのは可能である。noexcept演算子というものが、新しく定義されている。これについては、本の虫: noexcept operatorを参照。

2010-08-01

とうとうconstexpr specifierに到達

ようやく、constexpr specifierまでたどり着いた。しかし、これはしばらく執筆を保留しておいたほうがいいかもしれない。constexpr自体は、それほど分かりにくいものでもない。もし、まともな実装さえあれば、10分ほど遊ぶだけですぐに覚えられるだろう。残念ながら、まだまともな実装がないので、コードのtypoを検証できない。

追記:案の定、constexprに変更の動きが見られる。

下鴨納涼古本まつりが開催される

とうとう、待ち望んでいた8月になった。来る8月の11日から16日にかけて、下鴨納涼古本まつりが開催される。場所は、下鴨神社と糺の森だ。

今は、今昔物語と柳田國男全集があるので、とくに新しい本を買う必要はないが、なにか掘り出し物があるかもしれない。見物だけでもしてこようと思う。こういう古本市には、なかなか手に入らない本が、捨て値でたたき売られていたりするのだ。