2009-08-31

n2930: Range-based for loopについて

n2930: Range-Based For Loop Wording (Without Concepts)

今回、フランクフルト会議でconceptが廃止されたことにより、conceptに依存している機能は、すべてconceptに依存しないように変更しなければならなくなった。Range-based forは、conceptあってこその機能なのだ。concept mapがあるからこそ、既存の型にも、容易にRange-based forを適用できるようになるはずだったのだ。それが、conceptがない今、どうするのか。

答え:ADLを使う。

Range-based forは以下のような構文になっている。

for ( for-range-declaration : expression ) statement

これは、コンパイラによって、以下のように変換される。

{
 auto && __range = ( expression );
 for (auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) {
  for-range-declaration = *__begin;
  statement
 }
}

このコード上の、begin-exprとend-exprは、渡される型によって、異なる。

まず、配列の場合は、普通に期待されるとおり、すべての配列の要素に対して巡回するようになる。__begin +1, __begin +2といった感じだ。

それ以外の型の場合、begin-exprは、begin(__range)、になり、end-exprは、end(__range)、になる。

説明しよう。これは、begin(), end()という関数を、unqualified-lookupで呼び出しているのだ。しかも、この場合は特別に、通常のlookupではなく、ADLが用いられる。また、associated namespaceには、特別に、std名前空間も追加される。

また、std名前空間には、<iterator>, <array>, <deque>, <forward_list>, <list>, <map>, <regex>, <set>, <string>, <unordered_map>, <unordered_set>, or <vector>をincludeした時に、以下のような関数が導入される。

template<typename C> auto begin(C& c) -> decltype(c.begin());
 template<typename C> auto begin(const C& c) -> decltype(c.begin());
 template<typename C> auto end(C& c) -> decltype(c.end());
 template<typename C> auto end(const C& c) -> decltype(c.end());
 template<typename T, size_t N> T* begin(T (&array)[N]);
 template<typename T, size_t N> T* end(T (&array)[N]);

言葉で説明しても、よく分からないと思う。実際にコードで示すことにする。

#include <iostream>
#include <iterator>
namespace foo
{
    template < typename T >
    class container
    {
    public :
        T * begin() ;// 最初のイテレーターを返す。
        T * end() ;// 最後のイテレーターを返す。
    }
}

int main()
{   
    foo::container< int > c ;
    for (auto value : c )
    {
        std::cout << value << std::endl ;
    }
}

上記のコードが、Range-based for loopの基本的な使い方だ。メンバにイテレーターを返す、begin(), end()という関数を持っていれば、何もしなくても動く。<iterator>をincludeすることによって、std名前空間に、begin()を呼び出して結果を返すだけのbegin()関数が追加されるからだ。end()も同様である。

しかしもし、foo::containerが以下のようになっていたらどうだろうか。

namespace foo
{
    template < typename T >
    class container
    {
    public :
        T * hazimari() ;// 最初のイテレーターを返す。
        T * owari() ;// 最後のイテレーターを返す。
    }
}

この場合は、動かない。なぜならば、コンパイラは、どのようにfoo::containerを巡回すればいいのか、分からないからだ。従って、やり方を定義してやる必要がある。そのためには、begin()とend()を、ADLによって見つかるように定義してやればよい。

namespace foo
{
    template < typename T >
    T * begin( container<T> & c ) { return c.hazimari() ; }
    template < typename T >
    T * end( container<T> & c ) { return c.owari() ; }
}

これによって、Range-based forが動くようになる。ここで注意すべき事がある。このbegin()/end()は、foo名前空間の中に書かなければならない。グローバル名前空間に書いても、Range-based forは動かない。なぜならば、Range-based forでは、通常のunqualified lookupは実行されないからだ。

正しく言うと、必ずしもfoo名前空間の中で定義しなければならないというわけでもない。ただし、それを説明するには、ADLについて詳細に説明しなければならない。それには余白が足りない。

ここで、ふと、「もしcontainerがグローバル名前空間で宣言されていたら、begin()/end()をどこで定義すればいいのか。ADLではグローバル名前空間はlookupされないじゃないか」、と思ったのだが、おそらく、心配はないだろう。というのも、規格を読む限り、associated namespaceは、グローバル名前空間も例外ではないはずだからだ。ADLでは、グローバル名前空間もlookupされる場合がある。現状では、ADLは、unqualified-lookupでは名前が見つからなかった場合のみ実行されるので、そんなことは起こらないだけだ。グローバル名前空間もassociated namespaceたりえるのだが、現行では、ADLが実行されるということは、グローバル名前空間からは見つからなかったということなので、意識しないだけなのだろう。

今さら言うまでもなく、ADLは邪悪である。n2930の提案では、既存のコードが壊れる可能性がある。例えば、

#include <iterator>
#include <utility>

namespace foo
{
    template < typename T >
    class container { public : void begin() {} } ;

    template < typename T >
    void begin(T &) { }
}

int main()
{
    foo::container< std::pair< int, int > > c ;
    begin( c ) ;
}

このコードは、C++03では問題なくコンパイルされるが、C++0xでは、コンパイルエラーになる。なぜなら、<iterator>を導入することによって、std名前空間内に、

template<typename C> auto begin(C& c) -> decltype(c.begin());

といった、汎用的極まりない関数が導入されるからだ。このbegin()関数は、通常のunqualified lookupでは見つからないので、ADLが用いられるのだが、foo::containerのテンプレート引数に、std名前空間内のクラスが用いられていることにより、foo名前空間の他に、std名前空間も、associated namespaceに入ってしまう。その結果、begin()の呼び出しは曖昧になり、コンパイルエラーになる。

問題は、既存のコードだけではない。例えば、以下のコードもコンパイルエラーになる。

namespace foo
{
    template < typename T >
    class container
    {
    public :
        T * hazimari() { return NULL ; }
        T * owari() { return NULL ; }
    } ;

    template < typename T >
    T * begin( container< T > & c) { return c.hazimari() ; }
    template < typename T >
    T * end( container< T > & c) { return c.owari() ; }
}

namespace bar
{
    struct element {} ;

    template < typename T >
    void begin( foo::container<T> & c){} ;
}

int main()
{
    foo::container< bar::element > c ;
    for( auto value : c ) // エラー、begin(c)の呼び出しが曖昧
    {
    // 処理
    }
}

これも、理由は同じだ。テンプレート引数もADLのassociated namespaceになるというのが、問題なのだ。fooとbarは、それぞれ違う人が書いているコードだとする。fooさんはコンテナを実装していて、barさんはそのコンテナに入れる要素の型を実装しているものとする。barさんは、たまたま名前がbeginで、foo::containerを引数にとる関数を書いただけなのだ。それが、極めて不可思議な理由でエラーになってしまう。理由を理解するためには、ADLを理解していなければならない。

それもこれも、conceptが廃止されたからなのだ。嗚呼、concept。何為れぞ廃止せらるるや。

追記:temporaryの寿命の問題については、12.2 p5に、例外事項として付け加えるべきだと思う。begin, endという名前が重複してしまう問題については、std名前空間の中に、さらに別の名前空間を定義して、そこにbegin()/end()を入れるべきだと思う。例えば、

namespace std { namespace range {
template<typename C> auto begin(C& c) -> decltype(c.begin());
 template<typename C> auto begin(const C& c) -> decltype(c.begin());
 template<typename C> auto end(C& c) -> decltype(c.end());
 template<typename C> auto end(const C& c) -> decltype(c.end());
 template<typename T, size_t N> T* begin(T (&array)[N]);
 template<typename T, size_t N> T* end(T (&array)[N]);
}}

2009-08-30

旅日記

この三日、非常に疲れたので、その記録を日記にして書いておこうと思う。

28日、予備自補の教育訓練の最終日

予備自補の教育訓練の一課程の最終日であった。各課程の最終日は、官品の返納があるので、基本的に作業服や半長靴などの官品は装備しなくてよい。従って、0600の朝の点呼も、非常に楽であった。ラッパと共に飛び起きて、作業服や半長靴と格闘するという、毎朝の恒例行事がないからだ。Tシャツにジャージという、実に楽な格好で、舎前に集合すればよい。

まだ三課程しか受けていないから分からないが、基本的に、各課程の最終日というのは、午前中は座学、午後は返納と離隊の為の整備に当てられるようだ。最近はようやく、作業服のプレスも出来るようになってきた。

娑婆世界への帰還

さて、訓練の修了式を行って、1700に離隊した。今回は、二課程連続で受けている人、つまり、十日間も駐屯地内にいた人もいるためか、駐屯地を出ると、あちこちで、「うおお、シャバだ、シャバだ!」という声が聞こえてくる。やれやれ、娑婆世界に戻りたがるとは、煩悩を捨てきれぬ者どもよ。極楽往生はまず見込めまい。しかし、柵の中も、濃い人間関係を余儀なくされるので、浄土とは言い難いのだが。

さっそく電車で自宅に戻る。六時に自宅に着いた。見るとおにぎりと唐揚げが置いてある。どうやら、母親が事前に家に来て置いていったらしい。感謝しつつむさぼり食いながら、メールの確認や荷物の整理など、必要な作業をしているうちに、数時間という短い時間はあっという間に過ぎていった。

C++WGについて

何故、娑婆世界に戻って早々に、荷造りをしなければならないのか。実は明日の29日に、東京で、C++WG会議が開かれるからである。C++WGはC++標準化委員会の下位に属する各国の団体で、活動内容は、主に標準化委員会で採用が決まったペーパーやドラフトのレビューである。まともにC++を語れるほどの知識も実力も経験もないこの私が、どういうわけか、籍を置いている。

ただ、誤解を恐れずいうとすれば、仕事の出来るC++プログラマーが、単純にC++WGのメンバーに向いているかというと、必ずしもそうとは限らない。というのも、規格の文面がどうであるとか、ものすごく細かい細部の仕様を理解するだとか、変更が既存のコードに与える影響だとか、およそ現実の仕事のプログラミングには、まず確実に役に立たない知識の学習に、喜びを見いだす人間でなければならないからだ。

地獄の夜行バス

さて、京都駅から夜行バスで東京へと向かう。もちろん、3980円という最高に安い夜行バスのことである。通常の夜行バスにあるような、一席ごとに独立の参列シート、しかもシートの前後間隔にも余裕があるような、長距離移動用のバスなど望むべくもない。二列二列のシート、前後間隔は身をかがめる余裕さえないような、人間工学にまっこうから挑戦状をたたきつけているようなバスである。

29日、東京着

夜行バスに揺られること七時間、東京駅に着いた。C++WG会議が始まるまでには、まだ時間がある。ここは、神保町にでも行くとしよう。あそこならいくらでも時間をつぶせる。ただし、神保町の大抵の古本屋が開くのは、10時からである。あと三時間もある。

どうにも時間をつぶす当てがないので、山手線に二週乗ることにした。ご存じの通り、山手線は都内をぐるぐる回る環状線で、一週が約一時間なので、時間をつぶすという点において、じつに都合がいいのだ。車内で愚管抄を読んでいるうちに、二時間たった。9時である。山手線を降りて、神保町に向かった。

天国の神保町

さて、神保町だ。去年とは違い、今年は、特にどうしても欲しい本というのはない。強いていえば、左傳が欲しいとは思うが、あれは少々高いし、第一、欲しい理由というのも、左傳が気に入っているからではなく、森鴎外が左傳を愛読していたからに過ぎない。個人的には、左傳の文章は、味気ないと思う。たしかに、歴史書としては第一級に属することは間違いない。ただ、文章としては、それほど面白みがないのだ。淡々と出来事を編年体で記述しているだけの文章だ。

さて、神保町だ。いうまでもなく、私は本が好きである。しかも、古典が好きなのである。従って神保町は天国なのだ。何しろ本がある。それも大量にある。もはや絶版となった古典の全集などが、捨て値で投げ売られていることもある。最高だ。

まずぶらりぶらりと歩いていると、ある古本屋の軒先に投げ売られていた本のなかに、岩波文庫の明恵上人集を見つけた。もちろん、あの有名な夢記も載っている。夢記というと、私はかなり長い文章ではないかと思っていたのだが、どうも短い。岩波文庫50ページぐらいの分量である。どうやら、散逸して、今は残っていない部分もあるらしい。

なおもぶらぶらと歩いていると、ガレージセールといって、どれでも三冊で500円とか、一冊100円等という風に、本が投げ売られている所があった。せっかくなので、古典をいくつか買うことにした。

岩波の日本古典文学大系の、義経記、日本霊異記、今昔物語などを購入した。

C++WG会議

ふと気がついてみれば、もう12時を過ぎている。これはまずい。遅れてしまう。名残惜しいが、神保町巡りはここまでにして、山手線で田町駅に向かった。

やはり、少し遅れた。着いた時には、アキラさんが、レビューをしている最中だった。n2927で、lambdaの文面を書き換えようというものだ。他にも、興味深かったものを挙げてみる。

菅家さんの担当である、n2923は、微妙な論争になった。個人的には、STLが使えるような環境では、要素数という情報を保持しておくための変数と、その変数へのインクリメント、デクリメント処理をしたぐらいでは、パフォーマンス上の影響は無視できるぐらい小さいと思うのだが、やはり、コストがゼロではない以上、反対意見があるのも仕方のないことなのだろう。concurrencyの問題を指摘する人もいた。listのイテレーターの、別々の部分なら、複数のスレッドから同時に操作しても問題ないという類のものである。そもそもスレッド自体がC++03にはなく、C++03では、size()のcomplexityは規定されていないどころか、listの実装も規定されていないので、そんなlistの実装に依存したコードは、規格違反であり、問題外だと思う。新たにC++0xで縛るのかという意見もあったが、多分そういう環境では、自前のlistを書くべきだと思う。

n2928: Explicit Virtual Function Overridesは、興味深い機能だ。これは欲しい。

ADLは邪悪

長門かわいいの人梶本さんのレビューした、n2930: Range-Based For Loop Wording (Without Concepts)は、かなりの論争を引き起こした。conceptが廃止されたので、rangeベースのforループを、ADLを使って実現しようという、無理矢理の提案なので、それも当然だと思う。問題は、ADLというのは、基本的に邪悪な機能であり、思いも寄らない問題を引き起こすことがあるのだ。しかし、ADLというのは、思いも寄らない問題を解決するために導入されたという、逆説的な経緯もあるのだから、なおさらタチが悪い。

問題になったのは、以下のようなコードだ。

#include <vector>

namespace foo
{
    template < typename T >
    class container { public : void begin() {} } ;

    template < typename T >
    void begin(T) { }
}

int main()
{
    foo::container< std::pair< int, int > > c ;
    begin( c ) ;
}

さて、このコードを、みてみよう。begin()関数を、unqualified-lookupで呼び出している。グローバル名前空間にbegin()などという関数は存在しないが、引数として渡しているcの型は、foo::containerなので、ADLによって、foo::beginが呼び出されることになる。

優秀なC++プログラマでも、ADLについては知らない人も多い。というのも、ADLは、人間にとって自然にコードを書けるようにするための機能である。ADLを意図的に使った上記のようなコードは、まず書かれることがない。なぜなら、上記のコードを書くには、ADLについて理解していなければならないからだ。ADLについて理解していない人は、上記のコードは、グローバル名前空間にbegin()という関数が存在しないから、コンパイルエラーになると読むだろう。一般のプログラマがADLを知らないとしても、特に問題がない。ADLは上記の様な不思議なコードを書くために導入されたのではないからだ。主に、演算子のオーバーロードの為に導入されたのだ。

ところがである。C++0xでは、上記のコードはエラーになる。何故か。それは、ADLのassociated namespaceは、クラステンプレートのテンプレート引数の名前空間も含むからだ。だから、std::pairをテンプレート引数として指定すると、beginのlookupは、ADLによって、std名前空間からも行われるようになる。

さらに、<vector>をincludeすると、std名前空間に、以下のような邪悪極まりないテンプレート関数群が導入されてしまうのだ。

 template<typename C> auto begin(C& c) -> decltype(c.begin());
 template<typename C> auto begin(const C& c) -> decltype(c.begin());
 template<typename C> auto end(C& c) -> decltype(c.end());
 template<typename C> auto end(const C& c) -> decltype(c.end());
 template<typename T, size_t N> T* begin(T (&array)[N]);
 template<typename T, size_t N> T* end(T (&array)[N]);

従って、foo::begin()とstd::begin()とで、曖昧になってしまう。

会議には、上記のコードとは少し違った、実際には問題の無かったコードが提案されていた。後々から考えてみれば、そのコードには問題がなかったので、実際に問題のあるコードに修正した。その辺の経緯については、問題の本質ではないので省略する。会議に参加している人向けに、日本のC++WGのMLに詳しいことを投げておいた。

食事、一軒目

会議の後、一部のメンバーで食事に行こうという流れになった。

私が現在予備自衛官補をやっていて、melponさんが元常備自衛官だったということで、空気を読まずに自衛隊の話をした。匍匐前進で筋肉痛になったこと。居室内で台風が発生すること。腕立てのこと。やはり、予備自衛官補の訓練は、常備と比べてヌルすぎる。来年、常備に行くことを目指して、秋の試験も受けるが、悩みが一切無いわけでもない。どこかにいい技術系の仕事が転がっていないものだろうか。C++の規格などという、実用からかけ離れたことのみ学んでいるこの私が、一体何の役に立つかは、自分でも分からないが。

飲んでいる途中に、アキラさんのレビューしたn2927により、lambda expressionはdecltypeのオペランドとして使えないと規定されていることを知った。本の虫: lambdaとdecltypeを組み合わせれば、ユニーク型IDの必要ないc_functionがで取り上げたネタだ。一応、今回レビューするペーパーは、全部目を通したのだが、lambdaの新しい文面は、表面的には何も変わらないだろうとタカをくくっていたのだ。大間違いであった。ペーパーの冒頭に、ハッキリと書いてあることではないか。こんな重要な記述を見落としていたとは、情けない。

隣では、「Boostのmpl::stringを使って、コンパイル時C++コンパイラを作れ」だとか、「Adaはどのような言語だったか」などという話で盛り上がっていた。思えば、この一件目の食事は、まだ、比較的、平和的だったように思う。

酒、二軒目

さて、午後10時頃に一旦終わって、、まだ行ける人達で、二軒目に行くことにした。私は、当初、会議の後の食事会の事は考えていなかったので、あまり現金を持っていなかった。そこでコンビニに卸しに行こうとしたが、どうやら、地方銀行が、この時間取引できないらしい。仕方ないので、そのまま参加することにした。

二軒目になると、皆酒が回って饒舌になるのか、どうも話が変態的な方向に偏ってきた。もちろん、C++的な意味で。

melponさんは、「俺、コンパイル時Coroutine書いたあるぜ」と豪語したかと思えば、DigitalGhostさんは、「プリプロセッサでY Combinatorを実装する」などという話を熱心に語っていた。

特に興味深かったのは、D言語についてだ。上記の妄想が、Dでは妄想ではなくなってしまうらしいのだ。何でも、コンパイル時メタプログラミングで文字列リテラルを生成して、その文字列にたいしてコンパイルを実行することが出来るとか。さらには、コンパイル時ステップイン実行デバッグなんていう変態的な機能まで提供されているらしい。にわかには信じられないことではある。

DigitalGhostさんがメモ帳にシャーペンで筆記していた。私は、シャーペンは使いにくくないかと言ってみた。その場で書き殴るわけだし、メモ帳なんて安いものだ、一体何で、間違いを消す必要があろうか。間違いをしても、その次のページに書けばいいだけではないかと思う。ところが、DigitalGhostさんは、自分は八割方間違えるので、消しゴムは必須だと主張した。

思うに、真に優れた筆記具は、万年筆である。万年筆は少々高いが、インクは安い。つまり、高く付くのは初期投資だけで、ランニングコストは安いのだ。しかも、万年筆は、強い筆圧を必要としない。ところが、DigitalGhostさんは、自分は筆圧が強いので、むしろ逆にダメだと主張していた。

ところで、私は当日に、夜行バスで帰る予定であった。ところが、このような変態的な話をしているうちに、今日は帰らなくてもいいかと思い直し、帰るのをやめてしまった。結局、午後11時頃まで飲んでいた。

melpon宅に宿泊のこと

さて、この時間になると、たとえ銀行から金を下ろせたとしても、新幹線が動いていない。新幹線が動いていなければ、帰れない。結局、melpon宅に泊めてもらうことにした。どうやら、DigitalGhostさんが、明日のFLTVという集まりに参加するそうなので、その関係でmelpon宅に泊まるそうだ。

melponさんが、太っ腹にも切符を三枚買ってくれた。道中にも、変態的な話が続く。プログラマ的な意味で。

ブログ投稿中にブラウザがフリーズした場合、デバッガにアタッチしてメモリダンプから文字列を抽出すればいいということが語られていた。おそらくは、日記の登録ボタンを押してみたら,はてなが長時間のメンテナンス中だったときするべきこと - NyaRuRuの日記のことを行っているのだと思うが、ブラウザがフリーズしたにせよ、ブログサービスがメンテナンス中だったにせよ、解決方法は簡単だ。素直にBloggerを使えばいい。Bloggerは、投稿中の内容を変更すれば、自動的にサーバー側に保存してくれるし、メンテナンスということもまれである。あったとしても、極端に短い時間で終了する。ああ、これだからGoogleを離れられない。

melponさんがしきりに話すには、なんでも、家に犬を飼っているらしい。マンションがペット可だという。珍しいことだ。

駅からマンションまで歩く間、melponさんはしきりに、酷い股擦れに悩まされている様子だった。股擦れというのは、太ももが太い場合に起こる。melponさんはプロレスの経験があり、かなり恰幅がいいので、大変そうであった。太ももというのは、もちろん肥満して太くなることもあるが、運動によっても太くなる。私も、かなり体に不釣り合いなほど太い太ももをしている。おそらくは、中学時代のサッカーが原因であろう。

melpon宅に到着のこと

さて、melpon宅に到着して、ドアを開けると、すぐに犬の出迎えを受けた。Digital Ghostさんは、ややひいていた。

melpon宅には、様々の興味深い本があった。新紀元社のTruth In Fantasyシリーズの本がちらほらあったといえば、分かる人は分かるだろうと思う。昔の武器やファンタジーが好きなのにも関わらず、新紀元社を知らない人間はモグリである。もっとも、これはmelponさんの趣味ではなくて、同居人の趣味なのだそうだが。

ハルヒの小説があった。例しに冒頭を読んでみたが、どうもおもしろさがよく分からなかった。なんだか文章が稚拙である。まあ、最近は古典しか読んでいないので、違和感も多いのだろう。ラノベは、高校時代の一時期にハマったこともあったが、今は全く読んでいない。

犬がしきりに吠える。膝の上に乗せてやると、吠えることはなくなるのだが、どうにも落ち着いてくれない。膝の上で、せわしなく動き回る。melponさんの膝の上では、やたらとリラックスしているので、やはり慣れているのだろう。

melponさんのPCは、非常に豪快な冷却方法を採用していた。見た目的に、よく冷えそうだというのが分かる、数少ない冷却方法だと思う。

風呂に入った。予備自衛官補の訓練に参加していた時の癖から、今回は、着替えのシャツとタオルを持ち歩いていた。さらに、本を持っていくので、傷が付かないように、大きなバスタオルで包んでいた。予備自衛官補の訓練は、私をして、タオルやメモ帳を持ち歩く癖をつけたらしい。この場合においては助かった。風呂に入る前、同居人が、「左からボディソープとかシャンプーとか云々。ただし、ちょっと匂いがきついかも」と言っていたが、意味がよく分からなかったので、あまり気にはとめなかった。

風呂場には、ボディソープやシャンプーとおぼしき、様々な液体が並んでいた。不思議なことに、皆一様に、真っ赤なジェル状の液体であった。見ると、strawberryと書いてあったが、全く違和感はなかった。確かに、皆イチゴジャムのような見た目をしているのだ。

とにかく、そのイチゴジャムのボトルが大量にあるのだ。私は基本的に、石けんひとつあれば用が足りる人間である。坊主頭なので、頭を洗う為に、シャンプーなどと呼称される、特別な液体石けんが必要だと思わないのだ。それがこの数だ。壁一面にずらりとイチゴジャムが並んでいる。一体どれが体を洗うためのものなのか、さっぱり分からない。英文ラベルを読み比べて、それとおぼしきものを少し、ボトルより出してみる。まさにイチゴジャムのような手触りで、しかも甘ったるい匂いがした。どうみても、男児たる者の使うべきシロモノではない。

そもそも、melponさんがここに住んでいる以上、普通のボディソープのひとつもあるだろうと探してみたところ、分かりにくい場所に、申し訳なさそうに、普通のボディソープが捨て置かれていた。やれやれ、助かった。

風呂から上がってしばらくすると、DigitalGhostさんが、「俺の嫁」を披露していた。ラップトップのモニターの裏側に、眼球が巨大で、スーパーサイヤ人4のような髪型をした、人間の女性の絵が貼られている。DigitalGhostさんは、しきりにその絵を、嫁だと主張してはばからなかった。私は、「自分はあそこまで堕ちてはいない」という安堵感を得たが、また一方、「三次元に興味がないのは事実なので、自分も同類か」とも思った。

午前二時半頃、寝ることにした。

30日、起床

起床ラッパのならない生活はすばらしい。それほど大酒もしなかったので、二日酔いもなかった。寝ていた部屋には、なぜか、「らきすた」が何冊か積まれていた。アニメも原作も見たことはないが、もちろん、名前ぐらいは知っている。読んでみたが、らきすたは四コマらしい。知らなかった。

melponさん一騒動

melponさんとDigitalGhostさんが、FLTVに出席するため家を出るそうなので、それに併せて、私もお暇することにした。家を出るにあたってmelponさんがオロオロしていた。何でも、股擦れをどうしようか悩んでいるらしい。スパッツを探しているようだが、見つからないようだ。股擦れを防ぐべく、様々なアイディアが出された。

ファウンデーションを塗ってはどうか
いや、それは数時間しか保たない
ガムテープを貼り付けていこう
無理だった
いっそのこと油を塗っていこうか
サラダ油ならある

結局、出がけにスパッツを買うということになった。melponさんが服屋の中に消えていき、しばらくして、勝ち誇ったような顔をして出てきた。スパッツを買えたのだろう。

時間がないので、メシはコンビニで買うことになった。melponさんは肉を買っていた。

電車で移動中、melponさんがiPhoneを使っていた。非常に操作しやすそうだった。特に、日本語入力の方法は、よく考えたものだと思った。私もそろそろ、まともなブラウザを積んだ携帯が欲しいと思っていたが、iPhoneは良さそうだ。まともなブラウザを積んでいるとか、どこでも繋がるとか、帯域が太いということが重要なのはもちろんだが、入力方法というのも、問題になる。私は今まで、物理的なQWERTY配列キーボードを積んだ携帯が良さそうだと思っていた。しかし、実際に店頭で触ってみると、非常に使いづらく感じた。iPhoneもどきのタッチパネル式携帯は他にもあるが、文字入力がどうなっているのか、そこも調べる必要があるのだろう。携帯を選ぶ時の参考にしよう。

天国の神保町、再び

FLTVにも参加してみたかったが、もう人数制限の関係もあると言うことで、仕方が無く、お二方とは別れることにした。このまますぐに京都に帰ってもいいのだが、せっかく東京にいるのだ。行きたい所がある。もちろん、神保町のことだ。

というわけで、再び神保町に向かった。神保町で、四時間ぐらいぶらぶらと古本屋巡りをして、また本を何冊か買った。

疲労困憊しつつ帰路につく

心身共に疲れていた。本が重いのだ。昨日の時点で、すでに大量の本を買っていたのに、今日も大量の本を買ったものだから、肩にのめり込むぐらいリュックが重く、しかも手提げ袋まで持っている始末。疲れるのも当然だ。

フラフラしつつ地下鉄に乗り、大手町で乗り換えようとしたら、切符が改札口を通らなかった。どうやら、切符を乗り換えにしていなかったらしい。だいぶ疲れているようだ。東京駅で、新幹線に乗って京都に帰った。この際も、東北線と東海道線の改札口を間違えて乗ろうとしてしまい、切符が改札口を通らなかった。本当に疲れているらしい。切符を間違えて買わなかっただけ、まだ救いがあると言える。

私は新幹線が嫌いである。確かに、新幹線は乗心地がいいし、時間もかからない。それでも、私は新幹線が嫌いである。理由は、「旅をしている気分にならない」ということだ。東京-京都間は、二時間半ぐらいである。一市町村など、数分もしないうちに通り過ぎてしまう。本当に味気ない。鈍行ならば、静岡の袋井市や磐田市を通り過ぎる際には、ああ、かつてこの辺で暮らしていたんだと感慨にふける時間もあるのだが、新幹線にはそれがない。静岡の駅を越えて、YAMAHAのビルが見えたので、この辺は磐田なのだろうかと思った次の瞬間には、もう天竜川を渡って、浜松の駅に着いているのだ。これは旅ではない。単なる移動だ。

蓼莪

さて、味気ない移動をして、京都に帰ってきた。帰宅すると、留守中に母親が来たのであろう。おにぎりなどが置いてあった。すぐ食べられる菓子なども置いてある。米も置いてあった。そういえば、米がそろそろなくなりかけているのだった。買おうと思ったが、どうせ一週間ほど家を空けるので、その後でいいとおもって、そのまま出てきたのだった。嗚呼、蓼蓼者莪、匪莪伊蒿、哀哀父母、生我劬勞、欲報之徳、昊天罔極。

蓼蓼者莪、 匪莪伊蒿、 哀哀父母、 生我劬勞、 蓼蓼者莪、 匪莪伊蔚、 哀哀父母、 生我勞瘁、 缾之罄矣、 維罍之恥、 鮮民之生、 不如死之久矣、 無父何怙、 無母何恃、 出則銜恤、 入則靡至、 父兮生我、 母兮鞠我、 拊我畜我、 長我育我、 顧我復我、 出入腹我、 欲報之徳、 昊天罔極、 南山烈烈、 飄風發發、 民莫不穀、 我獨何害、 南山律律、 飄風弗弗、 民莫不穀、 我獨不卒。

選挙

まだ時間があるので、選挙に行った。私は外国人参政権に反対の意見を持っているので、今回の選挙については、明確に反対を表明している自民党に入れたが、結果は、民主党の大勝であった。民主党は、永住権を持つ外国人の、地方参政権を認めようという立場だ。このことについてIRCでつぶやいていたら、あるフィンランド人から、「つまり、日本は世界に合わせるんだな」という答えが返ってきた。不思議に思って調べてみたところ、どうやら、EU圏は、永住権を持つ外国人の地方参政権を認めている国が多いらしい。しかし、世界的に見れば、外国人参政権を認めている国は、少数派だと思う。

高速道路の無料化は、かなりいい案だと思う。もちろん、高速道路を維持するためには、かなりの金がかかる。そのぶんは税金で補うことになるだろう。ただし、高速道路の恩恵を受けていない日本人はいない。高速道路があるからこそ、コンビニのような店が成り立つのだ。高速道路が無料化されれば、物流がだいぶ変わってくるはずだ。

無料化すると常に渋滞するとかいう変な反対意見を出している人間もいるが、それは反論にすらならないだろう。有料でも渋滞は起きるのだから。

mepon宅よりの日記

本日は、C++WG会議を終えて、大いに痛飲し、melpon宅にて宿泊。

本来は、夜行バスにて帰宅する予定なりしが、思わぬ酒の誘いに断り切れず、むしろ半ば期待ししつつ、かかる自体いできて、melpon宅に宿泊することとなりぬ。

それにしても、久しぶりに酒を飲んだ。

さて、明日、どうやって帰るかを思案中。やはり、新幹線で帰るのが、最も手っ取り早い方法であろう。

2009-08-28

Still alive but no kicking at all

予備自補の訓練修了、非常に疲れた。

特に、伏せ打ちの姿勢と、匍匐前進で、翌日酷い筋肉痛になった。今はだいぶ収まったが、普段使い慣れない筋肉を使うのは、つらいことだ。

明日は東京に行かなければならない。来週は更に訓練がある。疲れるだろうが、まあ、所詮は五日単位なので、常備に比べたら楽なものだろう。

2009-08-23

予備自補:半長靴について

「軍靴の音」という比喩表現がある。この比喩の意味はさておき、一体軍靴とは、具体的には、どのような靴を指すのだろうか。

確か司馬遼太郎だったと思うが、旧日本軍は、まず洋服を着させることから始まったというような意味の文があった気がする。つまり、今までのような着物ではなく、洋服を着せたのだ。当然、下駄や雪駄の代わりに、洋風の靴を履くようになった。

欧米や、洋風の軍隊では大抵、半長靴を履く。これは、すねの半分ぐらいの長さのブーツである。

自衛隊の官品の半長靴には、旧型と新型がある。予備自補で履いたのは、旧型だった。旧型は、すね部分は、ひもをフックで引っかけるだけであり、なんだか心細い感じがする。

この靴、結構硬い。会わない人は、訓練の最後まで、この半長靴に悩まされることになる。そういう人は、文字通りの意味で、音どころか、軍靴そのものが嫌いになる。

ところが、私はといえば、この半長靴が気に入ってしまった。自分用にPXで売っている自衛隊仕様の半長靴を欲しいと思ったぐらいだ。ただ、やはり二、三万するので、買うかどうかは迷っている。半長靴によく会うズボンを持っていないという問題もある。

半長靴は、毎日磨く。ブラシでこすり、ウエスでこする。

余談だが、私はウエスの語源がよく分からなかった。そこで調べてみた所、面白いことが分かった。基本的に、ウエスというのは、使い古したボロ布を使う。シャツだとか靴下がよく用いられる。そういうボロ布は、wasteである。そこから来ている言葉らしい。

ただ、いかに頑丈な足の皮を持つ者であっても、やはり、分厚い靴下を履くべきである。

聞いた話では、常備自衛官の中には、靴の磨き方に独自の理論を持っている人が、少なからずいるらしい。特に、つま先の光らせ方については、異論が多いのだとか。

現状

予備自補の訓練に必要な物をカバンに詰めていったら、入り切らなくなった。まあ、この旅行用カバン、あまり大きくない上に、車輪も質が悪く、うまく地面を滑らすことが出来ないという欠陥品。来年までには何か新しい物を買おう。

どうしても、重くはないがかさばる物がある。そういうものはリュックにいれて背負うことにした。

2009-08-22

選挙の参考に

Google 未来を選ぼう 衆院選2009

とりあえず、自分の選挙区の全政党の「5つの質問」動画を見ている。このようなサービスは実にすばらしい。

基本的に、情報は、ザ・選挙 日本インターネット新聞JanJanから提供されている物らしいが、このサイト、非常に使い勝手が悪い。Googleのサービスは、とてもシンプルである。入力フォームがひとつあり、そこに選挙区を入力する。すると、候補者一覧がでる。一見しただけで、どう使えばいいのかわかるすばらしいUIである。一方、ザ・選挙サイトは、どこに何の情報があるのかさっぱり分からない。仮に情報量は多いとしても、ものすごく非人間的でダメなUIである。

幸徳秋水は意外と人間臭い奴だった

幸徳秋水に関する研究の本を読んでいるが、これがなかなか面白い。

書生の身分になって、実家から七円の仕送りをもらっていたので、吉原で遊びまくっていたとかいうこともあったらしい。

また、友人の小泉三申の言葉によれば、幸徳は、女は「美人至上主義」とでもいうような価値観を持っていた。一番目の妻との結婚は、写真一枚を見ただけで決めている。そんな結婚がうまくいくわけが無く、二ヶ月後に離婚するわけだが、その顛末も面白い。「里帰りしてみてはどうだね」と、笑顔で駅まで送り出してから、独り大酒して、誰にも相談せず、酔った勢いで離縁状を書き、酔ったままポストに放り込んだのだとか。また二番目の妻も、式の直前になって、友人の小泉に「失敗だ。これから飲みに行こう。式をすっぽかせば、あきれて帰るだろう」などと言っている。

また、中江兆民の門弟となっていた時に、こづかいに困って、艶小説を書いたこともあったのだとか。どんな小説だろう。気になる。

2009-08-21

lambdaとdecltypeを組み合わせれば、ユニーク型IDの必要ないc_functionが

追記:n2927の提案により、lambda expressionは、sizeof, alignof, decltypeのオペランドに使えなくなっています。理由は、実装が極端に難しくなるからとのこと。従って、以下の内容はobsolateであり、正しいC++0xではありません。(コンパイル時のユニークなIDとしての型は、需要があると思うのに、残念)

5.1.1 p2

The evaluation of a lambda-expression results in an rvalue temporary (_class.temporary_ 12.2). This temporary is called the closure object. A lambda-expression shall not appear in an unevaluated operand (_expr_ Clause 5). [ Note: A closure object behaves like a function object (_function.objects_ 20.7). —end note ]

c_function.hpp

c_functionは、関数オブジェクトでさえも、Cの関数ポインタにしてくれる、とても便利なライブラリだ。ところが、これには一つ問題がある。どのように使うかのコードを示せば、問題が分かるだろう。

typedef void (*func_ptr_type)( char const * ) ;

void caller( func_ptr_type ptr)
{
    ptr("hello,world") ;
    ptr("My hovercraft is full of eels.") ;
    ptr("") ;
}

struct Printer
{
    void operator () ( char const * ptr ) const
    {
        std::cout << "argument is: " << ptr << std::endl ;
    }
} ;

struct Counter
{
    void operator () ( char const * ptr ) const
    {
        std::cout << "argument has " << strlen(ptr) << " character(s)"<< std::endl ;
    }
} ;

int main()
{
    using redshift::base::make_c_function ;
    func_ptr_type c_printer = make_c_function< struct unique_id_type_0, func_ptr_type >( Printer() ) ;
    func_ptr_type c_counter = make_c_function< struct unique_id_type_1, func_ptr_type >( Counter() ) ;

    caller( c_printer ) ;
    caller( c_counter ) ;
}

ごらんのように、caller()はテンプレートではない、いたって普通の関数ポインタをとる、古くさいコードである。ところが、関数オブジェクトを何の問題もなく呼び出しているではないか。一体どうやっているのか。

c_functionの実装では、static変数を使って、関数オブジェクトのポインタを格納している。テンプレートを使えば、複数のstatic変数を使うことが出来るが、問題は、テンプレートのインスタンス化の際には、ユニークなIDとしての型がひつようなのだ。上記では、struct xxxという形で、ユニークな型を渡している。単にユニークなIDとして必要なので、実際のクラスを、どこか別の場所で宣言しておく必要はない。しかし、ユニークな識別子でなければならない。さもなければ、既存のstatic変数が書き換えられてしまう。これは、人間の手で書くには、問題がある。なぜなら、人間のすることは信用すべきではないからだ。ソフトウェアの少なからぬ数のバグが、typoによって生じているというのは、証明する統計データはないものの、間違ってはいないと思う。

ところで、C++0xには、lambdaとdecltypeが入る。これを使えば、上記の面倒なユニークIDとしての型を手書きする必要がなくなると思う。

まずlambdaだが、lambda expressionは、それぞれ、未規定のユニークな型であると規定されている。つまり、別の場所に書いてさえいれば、それぞれのlambda expressionの型は別で、しかもユニークであることが保証されているのだ。

ところが、lambda expressionはあくまでクロージャーオブジェクトである。型ではない。そこで、decltypeが役に立つ。decltypeは、lambda expressionから、その型を得ることが出来る。どんな型になるかは、環境依存だが、ユニークな型であることは、保証されているので、テンプレート引数に使える。

#define MAKE_C_FUNCTION( FUNCTION_TYPE, CALL) \
redshift::base::make_c_function< decltype([]{}), FUNCTION_TYPE>(CALL)

ただ、やはりプリプロセッサが必要になってしまうのはどうしようもない。それならいっそ、処理系によっては、ユニークな文字列や値に置き換えられる、pre-defined macroを提供しているプリプロセッサがある。処理系依存になってしまうが、そういう機能を使っても、目的は達せられる。

それに、c_functionも万能ではない、ユニークな型が必要なので、ループ内で、後で呼び出されるコールバック関数の為に使うと、問題になる可能性もある。

template < typename Iterater >
void init_callbacks( Iterater first, Iterater last, Iterater funcObjs )
{
    for ( ; first != last ; ++first, ++funcObjs )
    {
        first->set_callback(*funcObjs) ;
    }
}

このような例では、set_callback()メンバ関数が関数ポインタしかとらないので、c_functionでラップしたいとしても、不可能である。

結局、templateを使えと啓蒙運動をする方が、よほどマシだということになる。

ただ、lambdaとdecltypeによるユニークな型の生成は、テンプレートメタプログラミングに何かしら役に立つと思う。

2009-08-20

decltypeの訓練

こんにちは、脳内に優れたC++0xコンパイラをインストール済みのみなさん。今回は、あなたの脳内コンパイラが規格準拠かどうかを、さらにテストしてみましょう。

まずは、decltypeの決まりごとからです。優秀なみなさんのことですから、decltypeの決まりごとぐらい、当然暗記しているのは分かっていますが、念のために引用しておきます。

The type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression or a class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
— otherwise, if e is a function call (5.2.2) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e.

まず、ひとつめの検証からいきましょう。人間コンパイラを自負している優秀なみなさんのことですから、C++0xドラフト規格の書かれている神聖なる言語、英語ぐらいは当然読めることかと思いますが、一応、翻訳します。

decltype(e)の型は、以下のように定義される。

いよいよ実際に特訓していきます。まずは最初の条件からです。ワクワクしますね。

もし、eが無括弧のid-expressionか、class member accessであれば、decltype(e)の型はeという名前の要素の型である。もし、そのような要素がないか、あるいは、eがオーバーロード関数群であれば、プログラムはill-formedである。

この条件に合致するコードとは、以下のようなものです。ちゃんと自前の脳内コンパイラでコンパイルしてから、答え合わせしてくださいね。id-expressionか、class member accessのどちらなのか、decltypeの型は何なのか。

char a ;
decltype(a) ;

int b ;
decltype(b) ;

int * p ;
decltype(p) ;

int i ;
int & r = i ;
decltype(r) ;

int && rr = i ;
decltype(rr) ;

int const c ;
decltype(c) ;

int volatile v ;
decltype(v) ;

int const volatile * const volatile cv ;
decltype(cv) ;

struct D {} d ;
decltype(d) ;

struct E { typedef int type ; } ;
decltype(E::type) ;

void func(int x, int y) ;
decltype(func) ;

struct F{ int a ; } f, * fp ;
decltype(f.a) ;
decltype(fp->a) ;

答えです。

// id-expressions

char a ;
decltype(a) ; // char

int b ;
decltype(b) ; // int

int i ;
int & r = i ;
decltype(r) ; // int &

int && rr = i ;
decltype(rr) ; // int &&

int const c ;
decltype(c) ; // int const

int volatile v ;
decltype(v) ; // int volatile

int const volatile * const volatile cv ;
decltype(cv) ; // int const volatile * const volatile

struct D {} d ;
decltype(d) ; // struct D

// qualified-id
struct E { typedef int type ; } ;
decltype(E::type) ; // int

void func(int, int) ;
decltype(func) ; // void (int, int)


// class member access

struct F{ int a ; } f, * fp ;
decltype(f.a) ; // int
decltype(fp->a) ; // int

では、ill-formedな例を挙げてみましょう。なぜill-formedなのか、脳内コンパイルのエラーメッセージを読んでくださいね。

decltype(Nudge_Nudge) ;

void func(char) ;
void func(int) ;

decltype(func) ;

おわかりでしょうか。では注目の答えです。

// エラー:Nudge_Nudgeという識別子は定義されていない。
decltype(Nudge_Nudge) ;

void func(char) ;
void func(int) ;

// エラー:funcには複数のオーバーロード関数がある。
decltype(func) ;

だいたい、チョメチョメなんて存在するわけがないですからね。幻想ですよ。

さて、次の条件に行きましょう。ゾクゾクしますね。

それ以外の場合で、eが関数呼び出しか、オーバーロード演算子の呼び出し(括弧は無視される)であれば、decltype(e)は、静的に選ばれた関数の戻り値の型である。

簡単ですね。では、関数呼び出しの例を挙げますので、さっそく脳内コンパイルにかかりましょう。

void a(void) ;
decltype(a()) ;

int b(int, int) ;
decltype( b(0,0) ) ;

int c(int) ;
float c(float) ;
double c(double) ;

decltype( c(0) ) ;
decltype( c(1.0f) ) ;
decltype( c(1.0) ) ;
decltype( c('a') ) ;

いかがですか。あなたの脳内コンパイラのパフォーマンスはどうでしょう。何分もかかったりしていませんか。それでは答えです。

void a(void) ;
decltype(a()) ; // void

int b(int, int) ;
decltype( b(0,0) ) ; // int

int c(int) ; // #1
float c(float) ; // #2
double c(double) ; // #3

decltype( c(0) ) ; // int(#1が選ばれる)
decltype( c(1.0f) ) ; // float(#2が選ばれる)
decltype( c(1.0) ) ; // double(#3が選ばれる)
decltype( c('a') ) ; // int(charからintへの暗黙の型変換の結果、#1が選ばれる)

関数呼び出しは、戻り値の型になります。最後のdecltypeは、charからintへの暗黙の型変換が行われています。decltype(e)のeのexpressionが評価されることはありません。ただし、評価された場合の型は、評価しなくても静的に判断できます。したがって、関数定義は必要ないのです。

では、オーバーロード演算子の呼び出しに移りましょう。脳内コンパイルスタート!

decltype(1 + 1) ;
decltype(1 + 1.0f) ;
decltype(1.0f + 1.0) ;
decltype(1 + 1 * 1 / 1) ;
decltype((1 + 1)) ;

int i = 0 ;
decltype(++i) ;

struct A{} ; struct B{} ;
struct C{} ; struct D {} ;

C operator + (A, B) ;
D operator + (A, C) ;
D operator + (C, A) ;

A a ; B b ; C c ; D d ;

decltype(a + b) ;
decltype(a + c) ;
decltype(a + b + a) ;

int *p ;
decltype(*p) ;
decltype(&p) ;

さあ、この辺は少々難しいかも知れません。脳内コンパイラの規格準拠度が試されます。

decltype(1 + 1) ; // int
decltype(1 + 1.0f) ; // float
decltype(1.0f + 1.0) ; // double
decltype(1 + 1 * 1 / 1) ; // int
decltype((1 + 1)) ; // int

int i = 0 ;
decltype(++i) ;// int

struct A{} ; struct B{} ;
struct C{} ; struct D {} ;

C operator + (A, B) ; // #1
D operator + (A, C) ; // #2
D operator + (C, A) ; // #3

A a ; B b ; C c ; D d ;

decltype(a + b) ; // C(#1が選ばれる)
decltype(a + c) ; // D(#2が選ばれる)

// +演算子は左結合なので、(a + b) + aと解釈される。
// a + b の型は、#1が選ばれ、C、
// C型の値 + aは、#3が選ばれ、D。
decltype(a + b + a) ;// D

int *p ;
decltype(*p) ; // int &
decltype(&p) ; // int **

+-*/といった二項演算子は、数の型変換を行った後のオペランドの型を返します。++演算子は、オペランドの型を返します。それさえ分かっていれば単純ですね。

ポインタの苦手な人は、最後で頭がカーネルパニックを起こすかも知れません。しかし、落ち着いて考えれば、簡単に分かることです。

さあ、いよいよ三つ目の条件です。ドキドキしますね。

それ以外の場合で、eがlvalueならば、decltype(e)はT &である。Tはeの型である。

もちろん、ここまで読み進めることができるほどの優秀な脳内コンパイラをお持ちのみなさんならば、解説の必要はないとは思いますが、それでも念のために解説します。括弧が無い場合は、すでに、最初の条件に合致しています。すると、残るのは、括弧でくくられている場合です。例をどうぞ。

int a ;
decltype((a)) ;
decltype(((a))) ;
decltype((((a)))) ;

int i ;
int & r = i ;
int && rr = i ;
decltype((r)) ; 
decltype((rr)) ;

Brain Compiler ver 2.0 initiating... done.
parsing... done.
lexical analyzing... done.
semantical analyzing... done.
wasting brain resources...... remaining ∞

int a ;
decltype((a)) ; // int &
decltype(((a))) ; // int &
decltype((((a)))) ; // int &

int i ;
int & r = i ;
int && rr = i ;
decltype((r)) ; // int &
decltype((rr)) ; // int &

括弧は一つだろうが二つだろうが三つだろうが、結果は同じです。もちろん、脳細胞の数は有限ですから、脳内コンパイラがパース可能な括弧数も、現実的には有限ですが、理論上は無限です。

参照に関しては、すこし厄介です。参照の参照は認められていません。では、最後のコードはill-formedではないかというと、そうではないのです。実は、参照というのは、lvalue referenceもrvalue referenceも、lvalueなのです。従って、括弧内で使った場合は、lvalueになります。

さあ、いよいよ最後です。もうそろそろクタクタでしょうか。

それ以外の場合、decltype(e)はeの型である。

さて、これも数が多いのですが、ほんの一例を挙げていきましょう。あなたの脳はマルチプロセッサでしょうか。脳内OSはプリエンプティブなスレッドをサポートしていますか。

decltype(0) ;
decltype((0)) ;
decltype(0u) ;
decltype(0.0f) ;
decltype(0.0) ;

decltype("hello,world") ;
decltype(L"hello,world") ;
decltype(u"hello,world") ;
decltype(U"hello,world") ;


struct Foo
{
    Foo()
    {
        decltype(this) ;
    }
} ;

decltype([]{}) ;
decltype([]{}()) ;

さあ、お待ちかねの答えです。

// rvalues

decltype(0) ; // int
decltype((0)) ; // int
decltype(0u) ; // unsigned int
decltype(0.0f) ; // float
decltype(0.0) ; // double


// literals

decltype("hello,world") ; // char const [12]
decltype(L"hello,world") ; // wchar_t const [12]
decltype(u"hello,world") ; // char16_t const [12]
decltype(U"hello,world") ; // char32_t const [12]


// this
struct Foo
{
    Foo()
    {
        decltype(this) ; // struct Foo *
    }
} ;

// lambda expression

decltype([]{}) ; // 規定されていないユニークな型
decltype([]{}()) ; // void

最後の条件に合致する例としては、まず、rvalueが挙げられます。次に、リテラルの類です。thisはrvalue expressionで、3.10(Lvalues and rvalues)でlvalueであると言及されていないので、この条件に含まれます。lambda expressionもそうです。

あなたの脳内コンパイラの規格準拠度はどうでしたか。

中国の浅はかなプロパガンダ

レコードチャイナ:かつての超大国!日本はなぜ世界のリーダーになれないのか―米誌

2009年8月18日、米誌「World Policy Journal」夏季号は「日本はなぜ世界のリーダーになれないのか?」と題した記事を掲載した。新華網が伝えた。

記事は、かつて経済超大国として世界のリーダーにもなり得る存在と目されていた日本だが、今や中国やインドなどの台頭によりすっかり影が薄れてしまったと論じた。記事によれば、日本は過去40年間、世界第2位の経済力だけを武器に国際社会で高い影響力を発揮してきたが、もともと政治や軍事面での実力は伴っていなかった。第2次大戦後、奇跡的な経済成長を遂げた日本だが今やその伝説も幻となり、大国としての地位すら危うい。

こうなると国際貢献のあり方も変える必要に迫られると記事は指摘。これまでのように「何でも金で解決」という訳にはいかなくなるだろう。日本はすっかり国際社会における自らの役割を見失ってしまった。国内政治も混乱が続いており、今後の見通しは暗い。記事は、これほど短期間で国際地位が暴落した国も珍しい、と日本の没落ぶりを強調した。(翻訳・編集/NN)

huh!、所詮はイエロー・モンキーなジャップの国。見通しは暗いしダメダメだね。

果たして本当にそうなのか。2chで興味深い書き込みを見かけたので、自分で検証してみた。私は、何でも自分で検証せずには信じないタチである。

ます、レコードチャイナの記事には、ソースが欠けている。原文へリンクしないというのは、まともな文章ではない。原文はこれだ。

MIT Press Journals - World Policy Journal - First Page

さて、レコードチャイナの記事では、「米誌「World Policy Journal」夏季号」であると書いている。この「米誌」という言葉に注目してもらいたい。つまり、これは天下の合衆国アメリカ様のご意見なんだぞということを強調したいらしい。さて、実際はどうであろうか。この原文の、"Why Japan Can't Lead"の著者は、オーストラリアにあるニューサウスウェールズ大学の日本政治学の女性教授、Aurelia George Mulganであるという。つまり、これはオーストラリア人の意見である。この時点からして、米誌であることを強調しても、何の意味もないことになる。

さて、次に中身だ。原文からPDFが落とせるので読んでみよう。

Fifty years ago, Japan redefined itself as a model of economic development and a nation dedicated to peace.

五十年前、日本は経済発展のモデルであり、平和主義の地としてよみがえった。

おいおい、戦前の日本は経済発展のモデルじゃなかったとでも言うのか? 明治開国より驚くほど早く発展していたし、だいいち、明治以前でも、未開の土人の国ではなかったのだ。自国の言語を書き表す文字があった。それもかなり複雑な文字があった。経済的には、株という言葉が、わざわざ翻訳するまでもなく、すでにあったし、先物取引すら行われていたと聞く。平和というのは疑問だが、当時は列強による領土拡張のための侵略、植民地化が普通に行われていたではないか。日本だけを特別平和ではないとするのはあたらない。

yet Japan’s political or military status has not since World War II been commensurate with its economic power.

しかし、戦後の日本の政治と軍事は、経済力と釣り合っていない。

政治的には、非常に安定している国だと言える。
軍事的には、専守防衛を旨としているので、素人の目を楽しませるほどの派手なものはない。ただ、日本のレーダーは、大韓航空機撃墜事件の犯人特定の動かぬ証拠を示せる程度には優秀である。

Ueno Park in the center of Tokyo, better known for its cherry blossoms, is now home to an ever-expanding army of unemployed and homeless ex-salarymen, clustering together for moral support and assistance from public organizations.

桜で有名な上野公園は、ホームレスの巣窟となっている。

ホームレスは減っている。一時期は、サザエさんにもネタにされるぐらい、ホームレスは多かった。しかし今は、かなり少ない。それに、ホームレスというのは、その人間性にも問題がある。能力以前の話で、どうも、私の主観だが、酒におぼれている人間が多いのである。生活保護だとか居住の提供だとかの行政支援も行われているが、そういう人たちは利用しない。というのも、そこでは酒が飲めないから。

Those lucky enough to hold on to their jobs are squirreling money away as insurance for bad times. Affluent Tokyo residents no longer flock to Sunday shopping in the Ginza, the so-called “temple of luxury” and showpiece of brand-name consumerism.

たとえ定職にありつけている人でも、不景気のため、セコセコと貯蓄するだけである。トーキョーの金持ち達は、もはや、「贅沢寺院」と呼ばれる銀座で、ブランド品をあさったりしないのである。

だんだん筆の運びが怪しくなってきた。どこの三流週刊誌のゴシップ記事だよ。苟も日本政治学の博士号を取った教授の書く事だろうか。

Its armed forces have acquired modern, technologically advanced conventional capabilities, yet they are structured principally for defense of the homeland. Japan is committed to UN peacekeeping but not to the full spectrum of peacekeeping operations, which includes collective security.

武装軍隊は最新技術の先進的な兵器を購入しているが、専守防衛を旨としている。日本は国際連合の平和維持活動に参加したが、平和維持の完全な活動はできていなかった。例えば機密情報の収集だ。

なんだか反論するのもばかばかしくなってきた。国を守る程度の事は、古くさい時代後れの武器で十分だと言いたいのだろうか。PKOの目的とは、名前の通り、平和を維持する活動である。基本的には、紛争の当事者を停戦させ、合意を得たのちで、対立し合う集団の間に、監視役として、各国から軍隊を派遣する。PKOの活動(PKOの活動ってへんな言葉だが、日本語としてPKOが定着しているのだから仕方がない)の一つとして、平和が保たれているかどうかの調査も含まれる。それを機密情報の収集と言っているのだろうが。そんなことは日本の現行法では不可能だ。ちなみに、PKOでの自衛隊の活動らしい活動は、主に現地の支援、例えば、道路や橋の整備などだった。

Likewise, Japan is nominally committed to the U.S.- Japan alliance but not fully committed, given its rejection of collective defense.

同様に、日本は大抵、アメリカ合衆国に協力しているが、完全ではない。集団安全保障への参加の拒否などだ。

集団安全保障とは、こういうことをいうのであろうか。他国に対する武力の不保持を明記している憲法の下でそんなことができるわけがない。憲法九条の政府としての解釈は、憲法は武力の保持を否定しているが、自衛権は否定していない。つまり、自衛権のための武力の保持は、認められるという考え方である。自国が侵略されない限り、武力行使などできるわけがない。

もう読むのがいやになってきた。どこの三流ゴシップ記事だよ。

Far from being encouraged, political dissent that challenges the dominance of mainstream discourse is curbed by both overt and covert censorship as well as by the police who single out anti-government protesters for discriminatory treatment.

世論に対する政治的な反論は、明白もしくは暗黙的な検閲によって阻止されており、警察は反政府運動家を探して、差別的な扱いをしている。

少なくとも、非武装地帯を作ろうだとか、外国人参政権を認めようなどという主張が検閲されたり、警察によって捕まったなどという話は、日本では聞いたこともない。中国ならいざ知らず。これを伝えているのが、金楯、俗にグレート・ファイヤーウォール・オブ・チャイナで有名な中国の報道機関なのだが、自国のインターネット検閲に関してはどう考えているのだろうか。あるいは、反政府運動というのが、日本赤軍のようなものならば、当然、「差別的な扱い」をされるべきだと思うのだが。

もう疲れたので、2chネタの検証だけ行う。

Japan will have a Lower House election before mid-October, and for the first time, the LDP faces the real prospect of defeat. It’s up against a genuine, possible alternative governing party, the Democratic Party of Japan, or DJP, which has held a near-majority of the Upper House since the last election in 2007, producing a divided Diet.

民主党(Democratic Party of Japan, DPJ)を、かつて韓国に存在した、Democratic Justice Party(DJP)と混同しているという批判もあった。その前に正しく記述しているので、あるいはタイプミスであるのかもしれない。しかし、どうも文脈がおかしい。"or DJP for short" ならともかく、単に"or DJP"というのはちょっと疑問だ。Democratic Party of Japanの略がDPJであることは明らかである。わざわざ後々のために解説するまでもない。さらに決定的なことに、記事中のすべての箇所で、DJPを使っている。記事中にDPJの文字は存在しない。もはや弁論の余地がない。これはタイプミスではない。この女性教授は、明らかに意図的にかつて存在した韓国の政党の略称であるDJPを使っているのだ。この教授、本当に日本の政治学で博士号を取ったのだろうか。DJPなる日本の政党は存在しない。あるいはこの教授、日本と韓国を混同しているのではないだろうか。韓国であるならば、上記の検閲のことも、日本的な文化はだいぶ最近まで検閲されてきたし、分からないでもないのだが。

このゴシップ記事は、最後に以下のように結んでいる。

Unless Japan soon figures out how to resolve the current domestic political impasse and restore its political leadership’s ability to govern and rule, it will face the prospect of diminishing international power and recede ever farther from its long-held goal of being a major player on the international scene

日本がすぐに現在の国内の政治の行き詰まり脱却と、遵法を徹底させる政治指導力の回復に努めなければ、国際的な力の低下という失望と共に、国際社会での主要的な役割も地に墜ちるであろう。

ところが、レコードチャイナの翻訳では、

日本はすっかり国際社会における自らの役割を見失ってしまった。国内政治も混乱が続いており、今後の見通しは暗い。

最初の、"Unless Japan soon figures out..."という部分が完全に抜け落ちているのだ。これは中国側の意図的な誤訳であり、日本人をして、日本はもはや没落して希望がなく中国のような強国には比ぶべくもないという認識をせしめ、そのネガティブな意識をもって、実際に日本を没落させようという意図なのだろう。

結論、2chでの噂は正しかった。

sugar high

sugar high: 砂糖を食べ過ぎたようなハイテンション

砂糖の過剰摂取による行動異常を言うのだが、転じて、ハイテンションの意味で用いられるらしい。

色つきのシャボン玉が発明される

服や壁に色がつかないカラフルなシャボン玉「Zubbles」 - GIGAZINE

色つきなだけではなく、壁や服に色が付かないそうだ。シャボン玉は、子供なら一時間ぐらい熱中できるほど、単純で面白いものだが、色つきは面白そうだ。

Chromeが4.0.202.0にアップデートされた

Google Chrome Releases: Dev Channel Update

video, audio周りのバグがだいぶ修正されている。ようやく使える物になってきた。そろそろこのブログも、videoを使う物に書き換えるとするか。

それにしても、早めにflashでの動画表示に、自前のjavascriptコードを一枚かませるようにしておいて正解だった。これは、jw flv playerがころころ仕様を変える事への不安からだったのだが、こんな形で役に立つとは思わなかった。

ところで、今後動画をどうやってブログ上に載せようかという問題がある。

まず、現行のflashで再生していた時と同じ方法でのせるというものがある。これはid付きのdivをjavascriptのコードで置き換える物だ。既存の動画は、呼び出しているjavascriptの関数を書き換えることで、全く問題なくvideo要素に置き換えることが出来る。

javascriptの関数の名前や引数をリファクタして、これからの動画は新しいものを使うという方法もある。

問題はもう一つあって、それはフィードリーダー経由で、このブログを閲覧している人にも、動画を提供したいということだ。そのためには、video要素を直接書き込む必要がある。しかし、video要素を直接書き込んでしまっては、ドラフトとなっているvideo要素に変更があったり、将来的に、ブログ上のすべての動画に対して、何か面白いことをしたい時に、困る。従って、id付きのdivの中に、video要素をいれ、さらにそのidを、現段階では何もしないjavascriptの関数に渡すということも考えられる。

decltypeの二重括弧が参照になる理由

こんにちは。みなさんのような優秀なプログラマなら、C++0xコードの脳内コンパイルぐらい普通に行っていると思うのですが、何しろC++0xの型システムは厄介です。そこで今回は、皆さんの脳の規格準拠度を調べてみることにしましょう。

C++0xにはdecltypeがあります。delctypeも知らないようでは、もはやC++0xプログラマとしては恥ずかしくて人前を歩けません。ところが、decltypeは悉達多プログラマには、少々難しいのです。

以下のコード辺を脳内コンパイルしたとき、皆さんの脳内には、どのような型情報が構築されているでしょうか

int e ; #1

decltype(e) ; // #2
decltype((e)) ; // #3

まず、#1で、eの型は、当然intです。次のコードが脳内コンパイル可能かどうかは、皆さんの脳内コンパイラのバージョンによっても異なるのですが、今時C++0x対応でないコンパイラを脳内にインストールしている人はまずいないでしょう。#2のdelctypeの結果の型は、intになります。では、#3はどうでしょう。じつは、int &なのです。従って、正解は以下の通りになります。

int e ; eの型はint

decltype(e) ; // 文全体のexpressionの型はint
decltype((e)) ; // 文全体のexpressionの型はint &

「なんで括弧で囲っただけで結果が変わるんだ。そんなの全然C++らしくないじゃないか。lispとかいう月の言語ならともかく」と、お思いになる方もいらっしゃるかもしれません。しかし、上記の挙動は正しい物です。

上記のコードを正しく脳内コンパイル出来た方は、もうこれ以上、ここに有益な情報はありません。お帰り下さい。ただし、「自分の脳内コンパイラがエラーを出したから、上記コードは間違っている」というエラーを返す、時代後れな脳内コンパイラをご使用の方は、どうか続きをお読みになって、脳内コンパイラをアップデートしてください。

まず、decltypeの仕様です。7.1.6.2のp4に書かれている通り。

The type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression or a class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
— otherwise, if e is a function call (5.2.2) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen function;
otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e.

ごらんのように、"unparenthesized id-expression"の場合はそれ自体の型、それ以外の場合で、lvalueならば、参照型と書いてありますね。実は、無括弧(unparenthesized)という文面は、この続きの文章を読む必要の無かった、最新の脳内コンパイラをインストールしている方には、必要のない言葉なのです。もし、この「無括弧」という単語が無かったとしても、上記コードの挙動は変わりません。この言葉は論理的な思考の出来ないド低脳、もとい脳内にバグのある方にとっても、意味を明確にするために、特別に書いてあるに過ぎないのです。

上記コードに必要な部分だけ抜き出すと、「eがid-expressionの場合は、e自体の型。それ以外の場合で、eがlvalueならば、参照型」と書いてあります。上記コードでは、クラスメンバーアクセスだの関数呼び出しだのといったことは行われていないので、この場合、気にする必要はありません。id-expressionとは、この場合、変数名という識別子です。上記コードのdecltype(e)では、一番最初の条件に合致するので、型はintになります。

さて、primary-expressionについて思い出してください。忘れてしまったバギーな方の為に、これも規格を引用しておきます。5.1.1に書かれている通り、

primary-expression:
  literal
  this
  ( expression )
  id-expression
  lambda-expression

さて、これをみれば一目瞭然で、id-expressionと、括弧でくくったexpressionは、正しい脳内コンパイラでは、別物として扱われているのです。正しい脳内コンパイラをお使いであれば、当然この辺は正しく解釈します。するべきです。しなければなりません。

さて、もう一度decltypeの決まり事を考えてみましょう。「eがid-expressionの場合は、e自体の型。それ以外の場合で、eがlvalueならば、参照型」です。eはid-expressionです。しかし、(e)は、もはやid-expressionではないのです。id-expressionを包括する別のexpressionです。ただ、id-expressionも包括できるというだけに過ぎません。id-expressionを括弧でくくった結果は、もはやid-expressionでは無くなります。従って、それ以外の場合になります。さて、(e)はlvalueでしょうか。これは疑う余地なくlvalueです。従って、「それ以外の場合で、eがlvalueならば、参照型」という条件に合致します。よって、decltype((e))はint &となります。

この続きを読む必要の無かった、普通のC++0xプログラマは、こうした型システムの計算を、脳内で瞬時に正しく行っているわけです。さて、皆さんの脳内コンパイラはdecltypeに対応しましたか。

追記:言語的には、論理的なのかも知れないけど、人間的には論理的には思えないんだよね。

  1. (expression)のexpressionを対して、
  2. (expression)という形式で無くなるまで1. を実行する。
  3. もし、expressionがid-expressionであった場合、decltypeではid-expressionとして扱う

というような仕組みがあってもいいんじゃないかな、とは思った。

2009-08-18

世界は俺を笑わせてくれるために存在するのではないかと疑うニュース

小池氏、幸福実現党とタッグ結成も「金正日拘束」「ミサイルUターン」にドン引き…東京10区:社会:スポーツ報知

東京10区から立候補する自民党の小池百合子元防衛相(57)が17日、幸福実現党の泉聡彦氏(38)との共闘を宣言した。

10区では無所属での出馬を予定していた小林興起氏(65)が民主党の比例東京ブロックに公認され、民主候補の支援に転身。これに危機感を持った小池氏の陣営は、14日に泉氏に選挙協力を打診した。これに泉氏は「小池さんと志は一緒」と回答、あっさり不出馬を決めた。

17日は、北朝鮮による拉致工作の拠点とされる東京・池袋のクラブ「ニューコリアン」跡地前で2人そろって演説。「自公」ならぬ「自幸」の共闘に、小池氏は「幸福実現党と拉致問題についてしっかりと協力していきます」と語った。

ただ、泉氏が「北朝鮮にレンジャー部隊を送り込み、金正日を拘束して東京で裁判にかける」と仰天プランをぶち上げると、小池氏の表情は若干曇り引いた感じに。さらに「小池さんは、(幸福実現党の比例東京ブロックで出馬する)ドクター中松さんの『ミサイルUターン技術(撃ち込まれたミサイルをUターンさせ自爆させる発明)』にも理解を示されております」と畳み掛けられるとそそくさと車に乗り込んで、演説会場を後にしていた。

笑うしかないな。幸福実現党と手を組むということは、こういうことになると分かりきっていたはずなのに。こんな人間が自衛隊のトップから二番目(一番目は内閣総理大臣)にいたとは恐ろしい。

2009-08-17

今日、気になった文章

ガラパゴスの片隅でドンキホーテ扱いされないために - 雑種路線でいこう

この国にはプリンシパルがない。たった数十件の個人情報の入ったファイルを含むハードディスクを暗号化したPCを紛失しただけで個人情報流出として新聞の社会面に取り上げられる一方で、ケータイ・コンテンツでは簡単に名寄せに使える鍵が利用者から意識されず保護されないままネット上で流通している。かと思えば未だに社会保障番号は振られず総選挙の度に年金の名寄せ問題が争点となる。考えれば考えるほど支離滅裂だが、それなりの理屈と経緯と均衡で結果的にそうなっているのだろうし、他の世界も多かれ少なかれ矛盾に満ちているし、それを理不尽と感じているうちは何かが見えていない場合が多い。

それはそうだ。日本の携帯サイト(笑)の悲惨さは目に余る。また、国民にユニークな番号を振るのをあれだけ反対しておきながら、年金の不整合があると批判するというのも解せない。

ただ、以下には賛同できない。

個体識別情報に限らず端末や個人の認証の在り方は、当面ホットな話題であり続けるだろう。ネット犯罪対策のための年齢確認や社会保障カード、電子私書箱やライフログとも関係してくる。1990年代後半から暗号やら電子マネーを追っかけていた人間としては2010年も迫ろうというこの時代に、相変わらずWebサイトへのログインにID・パスワードを使い、SSLでクレジットカード番号を預け、単なる文字列で端末認証を行うとはどんな技術者の怠慢かと考えさせられる。あの時代だけで数千億円も研究開発に投資されて技術のピースは揃っているはずなのに、何故こんな低レベルの議論が未だに続いているのか。ブラインド署名は、属性証明は、三角決済はどこへ消えてしまったのだろうか。

Webサイトの認証に、指紋や静脈などの生体認証を使うとして、まず生体の読み取り装置が必要だし、その読み取った情報を、どのように符号化するかということも統一した規格にしなければならない。読み取り装置ごとにてんでバラバラでは話にならない。Web開発者側にサポートさせるには、読み取り装置がマウスやキーボードと同じぐらい普及していなければならない。

2009-08-15

lambdaのちょっと分からない点

以下の場合を考える。

class Foo
{

int x ;

public :

void f()
{
  // f()の中で百個の自動変数を使う。
  int val001, val002, val003, /*...*/ val100 ;

  // lambda expression
  [&]{// #1
    // ここで、valXXXなる一連の変数を全部使いたい。

     // さらにlambda expression
    [&]
    {// #2
     // ここで、#1の直前のメンバ関数であるf()のthisを使いたい。
     // と同時に、valXXXなる一連の変数も使いたい。
      this->x = val001 ;
    }() ;
  }() ;
}

} ;

上記のコードは、おそらく失敗するであろうと思われる。というのも、lambdaは直前の自動変数しかキャプチャできないからだ。#1のキャプチャリストに、明示的に書いたとしても、#2で使うことは出来ない。なぜならば、キャプチャした変数は、lambdaのクロージャオブジェクトのメンバ変数という扱いだからだ。従って、上記コードの正しい例はこうなる、と思う。

class Foo
{

int x ;

public :

void f()
{
  // f()の中で百個の自動変数を使う。
  int val001 = 1, val002 = 2, val003 = 3, /*...*/ val100 = 100 ;

  // lambda expression
  [&]{// #1
     auto auto_val001 = val001 ;
     // 使う必要のあるvalXXXを、ここで全部明示的に自動変数に代入。

     // さらにlambda expression
    [&]
    {// #2
      this->x = auto_val001 ;
    }() ;
  }() ;
}

} ;

たとえ、#2でthisをキャプチャしても、それは#1のlambdaのクロージャオブジェクトのthisにはならない。#1の直前のメンバ関数のthisになる。したがって、this->val001などとやって、#2から#1のキャプチャした変数を全部使うなどと言う抜け道はない。もし本当に使いたいのであれば、#1のcompound-statement内で、地道に必要な変数を全部、自動変数に代入してやる必要がある。

どうも、lambdaのネストは使いづらいな。

追記:#2のthisは#1のキャプチャしたthisであり、つまり#1を直接包括するメンバ関数のthisなので、thisを自動変数にする必要はない。

七徳の舞

徒然草の第二百二十六段。

後鳥羽院の御時、信濃前司行長、稽古の譽ありけるが、樂府の御論議の番に召されて、七徳の舞を二つ忘れたりければ、五徳の冠者と異名をつきにけるを、心憂き事にして、學問をすてて遁世したりけるを、慈鎭和尚、一藝ある者をば、下部までも召しおきて、不便にせさせ給ひければ、この信濃入道を扶持し給ひけり。

この行長入道平家物語を作りて、生佛といひける盲目に教へて語らせけり。さて山門のことを殊にゆゝしく書けり。九郎判官の事は委しく知りて書き載せたり。蒲冠者の事は能く知らざりけるにや、多くの事どもを記しもらせり。武士の事弓馬のわざは、生佛東國のものにて、武士に問ひ聞きて書かせけり。かの生佛がうまれつきの聲を、今の琵琶法師は學びたるなり。

「樂府」というのは、白氏文集の新樂府中のことだ。では「七徳の舞」とは何なのか。これは秦王破陣楽の別名の事だ。七徳舞、七徳歌で構成されているらしい。

行長は、この七徳舞のうち、二つを忘れたので、五徳の冠者と呼ばれたわけだ。

ちなみに、白氏文集の新樂府中には、七德舞と題する詩がある。徒然草の文中では、白居易に関する議論の余興として舞われた、本当の舞の事を言っているのであって、直接には関係ない。しかし、探すのには、結構骨が折れたので、参考に挙げておく。

七德舞、七德歌、傳自武德至元和、
元和小臣白居易、觀舞聽歌知樂意、樂終稽首陳其事、
太宗十八舉義兵、白旄黃鉞定兩京、擒充戮竇四海清、
二十有四功業成、二十有九即帝位、三十有五致太平、
功成理定何神速、速在推心置人腹、亡卒遺骸散帛收、
饑人賣子分金贖、魏徵夢見天子泣、張謹哀聞辰日哭、
怨女三千放出宮、死囚四百來歸獄、翦須燒藥賜功臣、
李勣嗚咽思殺身、含血吮瘡撫戰士、思摩奮呼乞效死、
則知不獨善戰善乘時、以心感人人心歸、
今來一百九十載、天下至今歌舞之、
歌七德、舞七德、聖人有祚垂無極、
豈徒耀神武、豈徒誇聖文、太宗意在陳王業、王業艱難示子孫。

ちなみに、七徳という徳があるのかと思って探したが、どうもそんなものは見つからない。ただひとつ、左傳、宣公十二年に、「武有七德」だとか書いてある。おそらくこの七徳は、その少し前の分、「夫武、禁暴、戢兵、保大、定功、安民、和眾、豐財,者也」のことを言うのであろう。

頼豪の話は虚構だったらしい

平家物語の諸本と愚管抄に云ふ。白河天皇の御宇に、内宮の賢子に王子産ませ給ふべきと思し召して、三井寺に頼豪てふ阿闍梨の侍りけるに、この御門、「汝皇子祈出してんや、効験あらば勧賞は乞に依べし」と被仰含。頼豪、肝胆を砕て祈申ける程に、程なくして中宮、敦文親王を産ませ給ふ。

さて頼豪、勧賞に三井寺に戒壇を建てん事を乞ふ。御門諸宗に之の是非を問ふ間、独り山門の大衆のみ不肯。これによりて勅許なし。頼豪激しく腹立ちて、「ひ死にして、王子も取り参らせん」と云う程に、御門聞召して、親しき人をやりてこれを説得せんとすれども甲斐ぞ無し。やがてひ死ににこそ死ににけり。程なくして、王子三歳と申しけるに、死ににけり。

これは、平家物語の諸本と愚管抄の一致して伝えることである。その内容も驚くほど似通っている。ところが、この話は、ここでしか出てこないのである。そのほかの文書には、こんな話はまったく出てこない。そもそも、敦文親王が薨ぜられたのは、承暦元年の九月六日のことで、その理由は、疱によるものだというのが、複数の旧記に書いてある。だが、頼豪はそれより八年も後、応徳元年五月四日に、仏前に結跏趺坐して寂滅したという、確かな記録が残っている。すると、平家物語と愚管抄の話にある、頼豪が思い死にして、その後に王子を呪い殺したという話は、そもそも成立しない。

なぜこんな虚構の説話が、平家物語と愚管抄だけに共通して見えるのか。

愚管抄の作者は、近年の研究によれば、慈円の作であるというのが定説になっている。また、平家物語の作者は、徒然草の第二百二十六段の記述を信頼するならば、信濃前司行長が書いたものである。この段に書かれている慈鎮和尚というのは、慈円のことである。他にも、徒然草の第六十八段では、吉水和尚とも呼ばれている。

とするならば、愚管抄と平家物語の作者は、師匠と弟子の関係にあたるわけだ。案外、現在残っている有名な文章の世界というのは、狭いものなのかも知れない。

また、愚管抄が、原平家物語とでも呼ぶべき物を参照しているのは、読めば明らかである。特に、アホ右翼の重盛をやたらに持ち上げる平家物語を、ヒガ事と言っている。

現在、平家物語といった時、作者は単に独り行長のみではなくて、大勢の人の増補を受けたものを指すので、少し注意が必要なのだが。

ああ、それにしても、行長の書いた本来の平家物語は、どんな感じだったのだろうか。延慶本が、比較的よく伝えているとは言うが、それでもまだ、明らかに後世の加筆とおぼしき物があるらしい。

また、平家物語の原作者という究極の問題を、さらりと書いている徒然草というのが、すごすぎる。それでいて、徒然草は簡単で、現代でも広く読まれている。吉田兼好はよほどすごい奴だったのだろう。多分、横にいたらウザい奴だったとは思うが。

2009-08-14

Bjarne Stroustrup、Conceptと未来を語る

センスとフィーリングで大胆な意訳を試みた。Danny Kalevがやたらとウザい奴に成り下がっていたり、Bjarne Stroustrupがコミカルなまでにジジイ臭いのは仕様。ただ、DKの言い回しは、ちょっとやり過ぎたかも知れない。実際原文を読んでいると、これぐらいムカつく言い回しなのだが。

Page 1: Concepts: Disappointment Without Defeat

Danny Kalev

今回のconceptの失敗についてどう受け止めてますか。今回の事件をどう思いますか。これは、あるいは、将来的に新機能を提案する妨げになると思いますか。

Bjarne Stroustrup

C++0xにconceptを入れないと決定したことについてかね。ワシとしては、conceptが失敗したとは思っておらんよ。今回の問題は、個人的にはユーザビリティの問題だと思っておるんだが、まあ、せいぜい数週間もあれば、修正できたと考えておる。まあ、委員会は、それほど早く解決できないと考えておったようだな。皆、conceptのアイディア自体は気に入っておるんだがな。一度ドラフトから外されると、もう一度入れるには、また長い時間がかかると、あれほど言っておいたんだがな。「失敗」と「何百万人ものプログラマが使うのに十分な規格ではなかった」というのは、大きく違っていると言えるな

小石を町のこっちからあっちへ移動させるのは、砂粒を動かすのと同じぐらい、造作もないことだろう。しかしね、小石がどこへ移動しようが、誰も気になどしないが(靴の中にある場合は別だがね)、砂粒を動かすのが、時として非常に重要な場合もあるのだ。つまりは、現実に広く使われているC++を変更するのは難しいが、何百万人ものプログラマが恩恵を受けるかもしれんのだ。これこそワシが、大変で反発も多いものの、C++を改良しようとしている理由だ。

今回のことをどう思うかって。残念だね。だがめげたりはせんな。もっと酷いことになっていたかもしれんのだからね。例えば、問題のある「concept」を規格に入れてしまったかもしれん。

Danny Kalev

コンセプトの規格制定には、7年もかかってますよね。でも、STLの開発は、その半分程度の期間でしたよね。なんでconceptはこれほど難しかったのですか。

Bjarne Stroustrup

ワシは、conceptは2002年から始まったと考えておる。ワシが最初の設計のペーパーを発表したのは、2003年のことだ。Alex Stepanovが、完全なSTLの実装を、Andrew Koenigとワシに見せたのは、1994年のことだった。だが、2002年から2009年と、1994年から1998年とは、比べようがないな。Alexは少なくとも、1976年からSTLを開発しておったんだからな。

しかし、君の質問に答えてみるとだな。Conceptの規格を設計することは難しい。というのも、C++の型システムそのものだからだな。conceptの規格を正しく設計するというのは、C++の規格を、より明確にするということだ。C++標準ライブラリの規定も、より詳しく書かねばならん。言ってみればだね、conceptの規格を正しく設計するというのは、C++規格の不明確な部分を、整理するということだな。また、conceptの規格を正しく設計していれば、

  1. コンパイル時間が極端に増えたりなどせんし、
  2. 実行時のパフォーマンスが下がったりもせんし、
  3. ジェネリックプログラミングを制限することもないのだ。

ワシがフランクフルト前のペーパー(訳注:N2906:Simplifying the use of conceptsのことか)で心配したのは、最後の項目だな。みんな、最初ばかりを気にしておる。

思うに、みんな、conceptが何をするもので、どうあるべきかというのが、分かっておらんようだな。例で示そう。Conceptがあれば、違いの明らかなsort()を四種類書くことが出来る。

template<Container C>
  void sort(C& c); 
template<Container C, Comparator Cmp>
  void sort(C& c, Cmp cmp);
template<RandomAccessIterator Iter> 
  void sort(Iter p, Iter q); 
template<RandomAccessIterator Iter, Comparator Cmp>
  void sort(Iter p, Iter q, Cmp cmp);

大方の人には、違いが簡単に分かるだろう。そして、なぜC++98で規定しなかったのかと思うことだろう。sort()は一組のランダムアクセスイテレーターと、あるいは比較関数をも、引数に取る。だいたいみんな、もっと簡単な、sort()にコンテナをまるごと渡すようなことが、したいと思っておる。この例では、Conceptを使ってテンプレート引数に何が必要かを明示することによって、何が言いたいかを表現しているわけだな。その結果、オーバーロードできたり、テンプレート引数が間違っていた場合には、すぐにエラーメッセージが得られるというわけだ。たとえば、sort(lst.begin(),lst.end()) と書いておいて、lstが実はlistだった場合、C++98のエラーメッセージは遅れてリンク時になり、大抵は訳の分からんものになるのだ。Conceptがあれば、すぐにエラーがだせて、しかも正確だ。そうそう、型チェックとオーバーロードに必要なのは、宣言だけだ。普通の関数と同じで、定義(関数本体)は、どこにでも書けるというわけだ。

なぜこの実装が難しいのか。この例は簡単に説明、実装ができるが、テンプレートを書く際には、非常に微妙な型の詳細に依存しているのだ。例えば、テンプレート引数の型はtrivialなデストラクタがなければならんとか、テンプレート引数の型はmove-constructibleでなければならんとか、テンプレート引数の型はunionでなければならんとかだな。なぜなら、そのコードにおいては、そういうことが非常に重要だからだ。ワシの経験では、誰にも重要ではないC++の型システムというのは、存在せん。ある箇所で利用されるあらゆる可能性を、conceptで網羅するのは、非常に労力がかかる。そして、完璧にconceptで網羅しきれずに、問題になるのだ。

Conceptの利点は、テンプレートのユーザー(訳注:テンプレートコードを書くプログラマという意味ではなく、他人のすでに書いたテンプレートコードなライブラリを、ただ使うだけの、ユーザーとしてプログラマのこと)だけのものではない。テンプレートで実装する人(訳注:ユーザーが使うテンプレートなライブラリを書く、本物のプログラマのこと)にとっても重要なのだ。以下を考えてみ給え。

template<ForwardIterator Iter, class V>
  requires Comparable<Iter::value_type, V>
Iter find(Iter first, Iter last, V x)
{
  while (first!=last && *first!=x) first = first+1;
  return first;
}

これは、一見、正しそうに見える。実際、標準ライブラリのfind()は、一組のforward iteratorを取るし、値は、イテレーターのvalue_typeと比較可能でなければならない。これは、Conceptを用いて、標準ライブラリの規定を、簡潔に表現しているのだ。しかし、このコードの間違いは、forward iteratorは、+演算子を提供していないという所にある。++演算子だけだ。コンパイラは、上記のコードの、first = first+1の部分が間違っていることを、正確に指摘することが出来る。C++98だけでは、このエラーを見つけるには、テストか、頭のいいプログラマが必要になるのだ。

これについては、悪くは思わないだろう。もっとも、今回の論点は、もっと複雑で微妙な部分に関することなのだがね。

「エラーメッセージの良し悪しなんて、どうでもいいね」という人もおるかもしれん。まあ、どうでもいいわけがないのだが、これはconceptのほんのひとつの利点に過ぎん。もっと重要な利点とは、プログラミングスタイルとコード品質なのだ。関数の引数の宣言や引数の型チェックがない、C++以前のCの時代が想像できるかね。当時は、少なからぬ数の人が、

double sqrt(double);// モダンな関数宣言

上記を、下記の使い慣れた奴に比べて冗長すぎると抜かしていたんだ。

double sqrt();// 関数プロトタイプが無かった時代のCの関数宣言

コンパイル時間の増加を心配していた人もおった。実行時のオーバーヘッドを心配していた人もおった。そうだよ、本当にいたんだ。何しろ、intからdoubleへの予期しない型変換が発生するかもしれんのだからな。難しすぎることを心配していた人もおった。「果たして素人プログラマに関数宣言のような機能が使いこなせるだろうか?」とな。互換性も心配されていた。「コンパイル時及びリンク時に、古いコードとどうやって整合性を取ればいいのだ?」と。今となっては、どんな時代後れのCプログラマでも、「当時は、関数宣言すらなくて、一体どうやって、やっていけたんだろう」と疑うぐらいだ。

Danny Kalev

すると結論として、conceptがボロ負けしたのは、結局、一度に多くのことを修正しすぎたり、あるいは、C++をまるっきり新しい言語に仕立てようとしたからってことでしょうか? だいたい、C++は、templateにのめり込みすぎていて、ちょっと問題ありますしね。プログラマが読み書きするコードと、コンパイラが、テンプレートのインスタンス化の際に生成する、実際の、目に見えないコードとは、全然別物ですしね。言ってみれば、C++は現状維持した方がいいんじゃないでしょうか。templateは制限ありすぎですけど。

Bjarne Stroustrup

いや、ワシはConceptがボロ負けしたとは思っておらん。そもそもワシは、Conceptが多くのことを修正するだとか、C++を全然別の新言語に変えるものだとは考えておらん。Conceptはあるひとつの目的の為に導入されたのだ。ジェネリックプログラミングというテンプレートの高度な使い方を、直接言語側でサポートするためだ。現状では、コメントだとか、仕様書だとか、ドキュメントの中で記述しているようなことを、直接表現できるようにする為なのだ。よくデザインされたテンプレートコードというのは、引数の型にどのような操作をするのかを、きちんと考えて書かれているのだ。良いコードというのは、そういう必要条件という考えが、ドキュメント化されているものだ。標準規格のrequirements tableみたいな物だと考えてくれればいい。つまり、現在では、ほとんどのテンプレートコードは、暗黙のうちにConceptという考え方を使っているのだ。

なぜ言語で直接conceptという考え方をサポートする必要があるかと言えば、暗黙的な考えだけでは、十分ではないからだ。コンパイラは、コメントや、仕様書や、標準規格書や、プログラマ(当然私も含む)の脳内仕様を、読んでくれたりはしないのだ。つまり、言語としての、明示的なconceptのサポートがないというのは、バグや分かりづらいエラーメッセージの原因なのだ。テンプレート宣言におけるConceptと、関数宣言の引数(関数プロトタイプ)とは、皆が考える以上に、よく似ていると思う。

ワシは、テンプレートを「ちょっと問題あり」とは考えておらん。まず、これはマクロではない。コンパイラがテンプレートコードを変換して実行コードを生成するというのは、非テンプレートコードを置換するほど、心配するようなものではない。これを心配したり、テンプレートをマクロだと思う人がいるというのは、テンプレート引数の必要条件が、暗黙的だからだ。呼び出した時点でチェックされないのだ。そういう「変換」を心配するというのは神経質すぎる。逆に何も心配しないのなら、関数プロトタイプを使わずにCで書けばいい。

Page 2: Concept Awareness

Danny Kalev

Conceptがワーキングドラフト入りしてから数ヶ月後の、2000年3月に、Howard Hinnantが訊ねてましたよね。「素人プログラマにまでConceptを強要するリスクはどうだ。利点はあるのか」と。規格の設計段階でこういう意見が出されてないってのは驚きですよね。委員会には、もっとチェックやバランスが必要なんじゃないですかね。特に、Conceptみたいなドでかい新機能に対しては。

Bjarne stroustrup

委員会は完璧ではない。どんな団体だってそうだ。だがしかし、君の考えているよりはマシだよ。メンバーの何人かは、そういう質問を取り上げて、委員会を勝手だとか邪悪だとか言うだろうがな。

リスクを心配したり、リスクと利点を考慮したのは、何もHowardが始めてというわけではない。Conceptに携わってきた者全員が、第一日目から考えていた事だ。そもそもワシは、テンプレート規格の設計の第一日目から、テンプレート引数のチェックの利点欠点について考えていたのだ。1986年から考えていたのだ。D&Eを読み給え。 いまConceptが無い理由というのは、1988年当時は、柔軟性と汎用性、パフォーマンス、優れた早期チェックを実現するにはどうすればいいのか、分からなかったのだ。ワシの知る限り、当時は誰にも分からなかったのだ。結局ワシは、後期チェックと酷いエラーメッセージを犠牲にして、柔軟性と汎用性とパフォーマンスを重視したのだ。2006年には、ワシらには、問題の解決方法が分かっていた。この違いは大きい。2009年の問題は、一部の連中が、長年の研究と、実装とライブラリ設計の経験をもってしても、まだ「十分ではない」と考えていたことだ。つまり、Conceptの一部は、まだ標準入りするまでに、改良が必要であるということだ。特にワシとしては、Conceptの利用経験から得られた結果が、十分にConceptの規格の設計に反映されていないと思う。

Howardが、リスクと利点について質問したかどうか、ワシはよく覚えておらん。そういう質問をした人がおったことは確実だがね。実際の質問は、利用に関しての事だ。ワシの"simplifying the use of concepts"ペーパーによれば、

そのスレは、Howard Hinnantが、ライブラリの設計方針について、二通りの方法があることについて質問したことから始まった。ひとつは、エキスパートでもない多くの素人ユーザーもConcept mapを書く必要があるもので、もう一つは、あまりエレガントではないが、Concept mapと、そもそもconcept自体を使わないことで、素人ユーザーがconceptを理解する必要をなくすものだった。

すでにAlisdair Meredithが似たような質問をしておった。「auto conceptの使用は、レガシーコードのみに推奨されるべきだろうか」

ワシがその時も今現在も心配しておる事は、ユーザビリティだ。

委員会はISOのルールに従って運営されておる。堅苦しくて、保守的である。完全に公平である。誰でも、経験、教養、商業目的の如何を問わず参加でき、国単位での公平な投票が実施される。C++委員会のドキュメントはWeb上で公開されている。C++委員会はパイオニアなのだ。さらに、国際標準委員会と個々のメンバー達は、常にC++開発者と関わろうと努力しておる。ワシの出版物や、インタビューや、発言録は、そのほんの一部に過ぎん。

世界中で使われている言語を大幅に変えるのは、とても難しいことだ。それはある意味いいことで、他の独自(原語:proprietary)言語と比べて、C++の最大の利点とは、変化しにくいということだ。ワシは、これ以上、「チェックやバランス」が必要だとは思っておらん。強いて言えば、長期的な物の見方に囚われすぎていることぐらいか。

Danny Kalev

「チェックやバランス」についてもうちょっと具体的に言います。Boostという団体では、非公式の新ライブラリを、委員会が標準規格に入れる前に、実環境で実験でき、さらに多くのC++プログラマからフィードバックを得ることができます。しかし、委員会は、コア言語機能に対しては、似たような「実験場」を持っていません。つまりは、多くのコア言語機能は、まともな実経験やテストもなしに、ワーキングドラフト入りしているんじゃないですかね。Conceptはつまり、そういうことだったんじゃないですかね。コアC++実験団体というようなものはアリですか。役に立つと思いますか。

Bjarne stroustrup

conceptについての君の考察は間違っとるな。そういうことなら、ワシらはそういう「実験場」を持っておった。それはconceptGCCであり、主にインディアナやテキサスA&M大学でconceptを研究していた連中であり、主にBoostにおいてconceptをライブラリで使おうとしていた連中だ。conceptに対して心配していた事というのは、そうした研究が十分だったかということ、規格設計は十分練られていたかということ(ワシとしてはこれが一番心配だった)、もっと長い時間が必要で、規格制定を遅らせるのではないかということ(これが大半の人の心配していたこと)だ。

実際、すべての新機能は、なにがしかのコンパイラで実験されておったのだ。問題は、「規格設計を肯定するに足る実験はどの程度か」ということだ。機能毎に、答えは変わるだろうと思う。

主要なC++ユーザーやC++ベンダーから、年間数万ドルぐらいの支援金を募って、そういう「C++設計及び検証ラボ」なるものを設立、運営するのは、理にかなっておる。だが、だれも興味を持っておらんようだな。コモンズの悲劇によく似ているが、連中はむしろ、その100倍のカネを、なにがしかの製品につぎ込んで、また違った商業的利益を得たいようなのだ。

Danny Kalev

ていうか、よく分かんないんですけど、Conceptとrvalue referenceってデジャヴな気がするんですよね。当初、rvalue referenceは、大部分のユーザにも分かりやすいはずだったじゃないですか。でも今は違いますよね。素人プログラマも、move constructorとか、関数のオーバーローディングのルール変更とか、void A::f(); void A::f()&; and void A::f()&&;は全部違う意味だとか、rvalueはもはやlvalueにならないだとか、そういった事を知っていないといけないんですよ。rvalue referenceもConceptみたいに、複雑すぎて、不安定で、無駄にバカでかくなってるんじゃないですか。ホントに入れる価値あるんですか。

Bjarne stroustrup

もう一度言うが、「素人」というのはやめたほうがいい。まず図々しい。そもそも実際、ワシらは、外から見れば皆「素人」なのだ。現代のソフトウェアは、一人の人間の手に負えないほど複雑なので、皆素人に成り下がるのだ。ワシだって大抵の事に関して「素人」だし、君だってそうだ。ワシらが皆、大抵のことには「素人」なのだから、そういう言い方はやめて、さっさと勉強を始めないかね。「分割して攻略」(原語:分割統治 "Divide and conquer")が基本。abstractionとlayeringは役立つ方法だ。

すべての言語設計というのは、レイヤーという考え方がなされておる。もっとも簡単な例で言えば、プログラマは単に、std::vectorだとか行列クラスを使った際に、そのパフォーマンスが向上していることに気付くだろう。もっと詳しく見ていけば、move constructorがパフォーマンス向上の理由だということに気がつくだろう。コンテナをmoveすることは、copyよりも安くつく。さらに次のレベルでは、プログラマはmove constructorと、perfect forwardingな関数を書く。これは単に、std::move()とstd::forward()を使えばいいだけだ。ここで、rvalue referenceに対して、何か特別に理解しておかねばならんことなどあるのかね。大方のプログラマは、そこまで深くは首を突っ込まないだろう。思うに、ほとんどのプログラマは、「A::f()&&;とは一体どういう意味なのだ」とか、「std::move()は一体どうやって実装されているのだ」などという疑問が沸くことなどないだろう。そういう疑問は、理解しなければならないという理由があってこそ理解しようと思うのだ。ほとんどのプログラマは、もっと意味のある高級なコードを書くことに時間を費やすのだ。欲しいのは良いプログラマであって、言語ヲタクではない。

君がconceptとrvalue referenceに似たような感じを受けるのは、あながち間違いでもない。両方とも、型システムの問題なのだ。ゆえに、根本的に膨大で複雑なのだ。両方とも、「ユーザーインターフェース」を持っていて、細部が気になるプログラマを遠ざけてくれる。しかし、「concept」は膨大という以上のもので、長期的には、rvalue referenceより重要だ。

Page 3: Do We Still Need Concepts?

Danny Kalev

僕はあまりConceptのファンじゃないのですが、それでも、conceptとrequires キーワードの必要性は分かります。でも何で、concept mapとかaxiomなんかが必要なんですか。僕的には、言語を無意味に複雑化させる、机上の空論で非現実的なオモチャに思えるんです。まあ、役立つ利用方法もあるんでしょうが、最初は基本的なところから始めて、後から、注意深く拡張していった方がいいんじゃないでしょうか。

Bjarne stroustrup

やれやれ。キーワード数の削減が目的ではないのだ。ジェネリックプログラミングをサポートするために必要なのだ。conceptを便利にするには、現行の成功例を明確化してサポートしなければならん。conceptが受け入れられるためには、現行の成功例を完全にサポートしなければならん。さもなければ、constrainedとunconstrainedなtemplateがごっちゃになるだけだ。conceptが受け入れられるためには、「旧態依然のunconstrained」なtemplateから、「concept baseのconstrained」なtemplateへの、簡単な切り替え方法を、提供しなければならん。話はそれるが、ワシのフランクフルト前のコンセプト規格の設計に対するユーザビリティへの懸念は、このことも関係しておる。

concept mapについて考えてみることにしよう。conceptに任意の型を当てはめる、何らかの機構が必要だ。この機能がなければ、そのconceptを念頭に設計された型しか使えん。君が幸運の星の元に生まれたならば、たまたまシグネチャが一致しているかもしれんがね。そもそも、まったくの新機能なのだから、ユーザー同士が協調しあえば、conceptに一致するような型を強制できるだろうと思うかもしれん。ところが、C++というのは、1972年からの歴史ある、広く使われている言語なのだ。すでに多くの、想像もできないような型があるし、毎日毎日、新しい型やconceptが生み出されているのだ。

ちょっとここで言っておくが、ここ十年かそこらで、開発者というのはすでに、conceptを発明しているし、テンプレートをそのconceptに沿って書いているのだ。そういう「concept」は、単に明示化されていないだけに過ぎん。大抵は必要事項などドキュメントも不完全だし、勝手な仮定も含まれているのだがな。

そういうわけで、既存のconcept、例えば、random access iteratorと、既存の型、例えばint *を例に挙げよう。ここで、型を、conceptを要求するテンプレート引数で使いたいとする。一体どうすればいいのだ。言語にconcept mapがなければ、でっち上げるしかない。例えば、RandomAccessIteratorは、メンバー型(訳注:規格的に言えば、クラスにネストされた型)としてvalue_typeがなければならん。RandomAceessIteratorを使うテンプレートコードは、その名前を、引数の型のメンバー名として使うのだ。ところが、int *にはvalue_typeなどというメンバーはない。そもそも、int *にはメンバーなどというものがない。というのは、Dennis Ritcheが、ポインタにメンバーなど必要ないと、1972年に取り決めたからだ。タイムマシンでもない限り、当時int *にメンバーを付け加えるなんてことはできんし、そのためだけに、C with value_type(訳注:C with classesのもじり)などという言語を、1994年の時点で発明することもできなかったわけだ。

言語にconcept mapがなければ、自前のmapを作るしかない。この「map」は、int *のラッパークラスで、value_typeをメンバーに持っていて、そのほかのrandom access 操作もできる。幸運と優れたコンパイラに恵まれれば、int *とまったく変わらないパフォーマンスが得られるだろう。あとは、あらゆるint *を自前クラスのRandomAccessIteratorでラップするだけだ。ジェネリックプログラミングの経験があれば、この手のラッパークラスや、似たようなアイディアである、traitsは、よく見かけたことだろう。このようなworkaroundコードは一般的で、ジェネリックコードではお手軽だ。ただし書くのは面倒だし、大抵は汎用的ではなく、ごく限られたものにしか動かん。エキスパートでなければ理解しづらい。だから問題の元なのだ。

concept_mapは、このような現実的で根本的な問題への、直接的な解決方法なのだ。例えば、

template<class T> concept_map RandomAccessIterator<T*> {
typedef T value_type;
};

これは、T*をRandomAccessIteratorとして使えば、そのvalue_typeはTであるという意味だ。常の如く、どんな文法が一番いいのかということに関しては議論があるが、このようなことを表現する必要がある。「このようなことを表現」するのは、実際に必要なのだ。完璧で汎用的なworkaroundなど存在せん。だから言語機能として絶対に必要なのだ。concept mapなしで、conceptを使ったジェネリックコードなど、書きたいとは思わんよ。

simplifying the use of conceptsでの議論を、また持ち上げるようなことなどしないが、ワシの言いたかったことは、concept mapは無駄に使われすぎで、複雑で使いにくいという事だ。ワシはその問題を解決するための提案をした。何にせよ、存在しない操作を付け加えたり、名前を変えたりして、型をconceptに一致させるための仕組みとしての、concept mapは経験上必要で、議論の余地もないことだ。

すでに説明したように、conceptは指定された文法に対して動く。ある型が、具体的な名前による操作や型を持っていなければならないということを明示するのだ。例えば、random access iteratorとして使うためには、その型は*, ++, [], value_typeなどを提供していなければならんなどだ。常識的に考えて、これらの操作は「正しいことをする」と見なされていて、その「正しいこと」は、どこか別のドキュメントに書かれておる。この場合、C++標準規格だ。これはconceptが言語側でサポートされているかどうかに関わらず、一緒だ。テンプレートに対するドキュメントというのは、意味的な必要事項を書き上げたものなのだ。良いドキュメントほど、その必要事項も詳しく書かれることになる。ここでの問題とは、一体どこまで、意味的な必要事項を、言語側でサポートすればいいのか、またどうやってサポートするのか、ということだ。

axiomでは、コード中に、詳しい意味上の規約を、簡単な文法で記述できる。例えば、

concept ForwardIterator<typename X> : InputIterator<X>, Regular<X> {
  requires Convertible<postincrement_result, const X&>;
  axiom MultiPass(X a, X b) {
   if (a == b) *a <=> *b;
   if (a == b) ++a <=> ++b;
  }
}

この記述は、ForwardIteratorとは、InputIteratorであり、==などを提供するのRegularであり、シークエンスに対して、multiple passという公理が成り立つ。<=>とは同等演算子である。つまり、ForwardIteratorのaとbに対して、aとbが等しいならば、*aに対する操作は、*bに対する操作と等しい。高校の代数学が苦手な奴らは、はだしで逃げ出すことだろう。しかし、記述された論理というのは古典的で、汎用的で、意味を記述するのに効果的だ。

axiomの規格の設計には、二つの目的がある。

  • より詳しいドキュメントを記述させること。
  • プログラマは、コード上で直接、開発環境に情報を伝えられること。

多くの連中は、axiomの目的を、以下のように、間違って考えている。

  • axiomはコンパイラにより良いコードを生成させるためのものである云々。実際、axiomは、特にそういう用途に優れてはおらん。というのも、ワシらが使う型というのは、数学的な法則に従うものではないからだ。doubleのような浮動小数点数は、実数の法則には従わん。実数にはNaNなどないからな。intの類は、整数の法則には従わん。数学的な整数は、オーバーフローなどせん。もし、axiomを最適化の為に設計しておったら、今頃、大失敗しておったことだろうよ。
  • axiomは型を証明するためのものである云々。まあ、数学を勉強する際には、公理というのは、証明をするために使うものだ。さすがにワシも、C++コンパイラに定理の証明機能などというものを提案する気はない。
  • 提案されている述語理論(訳注:predicate logic)の文法で、十分に意味の記述が出来るのか、もっと拡張すべきではないのか云々。述語理論はとても長く、且つ、輝かしい歴史を誇っており、表現力がある。ワシは冒険的に拡張したりなどはせん。

というわけで、axiomの使用目的と、よくある誤解を説明してきたわけだ。では残った利用方法は役に立つのかというと、役に立つと言えるね。conceptのドキュメントには、多くの公理を用いているという現実がある。しかし、利点というのは実際に示すのが難しい。

ここでaxiomの具体的な使い方を説明したりはしないが(詳しくはN2887参照のこと)、conceptを使う上での難しい問題に、文法上はほとんど同じだが、意味が違う、複数のconceptというのがある。たとえば、foward iteratorとinput iteratorだ。ワシは、次のconceptの設計では、もっとaxiomを全面的に押し出して、意味上の違いを、扱いやすくするつもりだ。

Danny Kalev

最近のDDJの記事で、「ConceptはC++0xの根幹をなす新機能だ」って書いてますよね。ある人は、C++0xの「主要機能」だって言い切ってましたよね(N2893)。でも、Conceptが入らないって決まったとたん、なんかやたらとそっけないんですよね。例えばですね。Herb Sutterがブログに書いてますけど、「concept延期に関するWeb上のコメントを読んでると、技術的な不正確さもさることながら、C++0xにConceptが入らないというのは、何かとても重大なことのように考えているらしい。不思議なことだ」とか。結局Conceptなんてどうでもいいことだったんですかね。なんでこんな機能に、アホみたいに時間と人手をかけてたんですかね。

Bjarne stroustrup

ワシが書いていた事を全部引用すると、

「Conceptは、templateの使用をより論理的にしたり、標準ライブラリの規格を書き直したりすることにおいて、根幹をなす新機能であり、また、ジェネリックプログラミングを一般にも使えるようにするための主要な機能だ。」

これは、単に、

「ConceptはC++0xの根幹をなす新機能だ」

というのとは、だいぶ印象が違ってくるな。

それから、ワシとしては、concept自体を「主要機能」だと言ったりはしないな。というのも、あるひとつの機能だけをもって、その言語の「主要」であると言うなどという事は、意味が分からない。ほとんどの人にとって、C++0xの最も重要な新機能とは、並列処理(concurrency)の標準サポートだと思うな。conceptと同じで、taskやatomic typeなどを直接使うのは、ごく一部のプログラマだけだが、恩恵を受ける人は多い。C++0xの改良は、よりよりプログラムを書いたり、開発環境をつくるのに、役立つツールに重点を置いているのだ。単にその機能自体だけですばらしいというわけではない。

ワシが思うに、conceptとは、重要だったし、また将来も重要になるだろう。テンプレートのユーザビリティを向上させ、ジェネリックプログラミングの範囲を広げ、高品質なライブラリのサポートの為の、重要な機能だ。何十年もの長期的にみて重要なのだ。だが、普通のプログラマにおける、この先数年の重要度というのは、それほどでもないだろう。手遅れにならないうちに、conceptがどうしようもなく必要な時代に達しないうちに、改良したconceptを入れることも出来るだろう。

長期的な物の見方が重要だ。そもそも、ConceptはたくさんあるC++0xの改良点のうちのひとつにしか過ぎんのだ。たとえConceptなしでも、C++0xはC++98よりはるかに優れたツールとなるだろう。

Page 4: Commitees and Standardization

Danny Kalev

あなたは何度も、100人の委員会というのは、「革新的な設計に最適な場ではない」と言ってますよね。ぶっちゃけ思うんですけど、ISO標準化委員会ってもうオワッテルんじゃないですかね。RubyやPhtyonは「善き独裁制」(訳注:実装がひとつしかなく、基本的にただ一人の独断で開発されていて、その実装がそのまま仕様になるような言語のことを言うのか)モデルを使って、標準化をしてますよね。Linuxはコミュニティプロセスですよね。もっと何か、今の時代に合った、別のプロセスで標準化することを考えてみてはどうですかね。今みたいなやたら几帳面で面倒臭くてトロいようなのじゃなくて、もっとみんなが直接参加できるような感じの。

Bjarne stroustrup

ワシのペーパーを読んで見給え。標準化と進化のモデルに対する懸念が書かれておる。(HOPL3 paperHOPL2 paper)。それはともかく、ワシは「もっとみんなが直接参加できる」ことが、向上に繋がるとは思えん。言語の議論における、普通の「声」は、大抵、短期的な物の見方をしており、流行に振り回されていて、しかもただひとつの機能しか考えておらん。多くが「簡単で完璧な解決方法」とやらを複雑な問題に適用できると信じており、既存の何十億行ものコード、何百万人ものプログラマへの教育といった事への配慮が足りん。何年も辛抱強く、設計、標準化の為の、多大で面倒な、細部を明確にする仕事をしたいと思う者は、ほとんどおらん。ワシが見たところでは、「コミュニティプロジェクト」とやらは、すでによく知られた概念が存在する物にしか有効ではない。たとえば、LinuxにおけるUnixなどだ。根本的に異なる設計思想から選り分けるのは、難しいことだ。それと、C++の標準化は、完全なボランティア作業であることを知っておいてもらいたい。もしC++が、わずかでも報酬を支払うようになっていれば、また違った物になったかもしれん。

ワシは独裁主義が好きではないが、短期的に見れば、効率的で善政を敷くのかもしれん。だがワシが思うに、ほとんどの「善き独裁者」というのは、大抵その力に飲まれ、一般受けしない個人的な趣味の機能を入れたりするだろう。つまり勝手な独断に走るのだ。

C++では、独裁というのは未だかつて行われておらん。最初期を過ぎれば、ただひとつの実装なんてものは存在しなかった。C++は、そこらのスクリプト言語とは比べものにならぬほど、多くの企業の根幹に組み込まれてきた。さらに、1980年代後半から1990年代には、HP、IBM、Intel、Microsoft、Sunのような企業は、ただ一人の独断に左右されるような言語を、まともなビジネスで使いたいとは思わなかった。今だにそうだと思う。C++標準化の仕事は、主要なユーザーによってなされているのだ。

Danny Kalev

「委員会による設計」というアプローチって、失敗の元ですよね。conceptが批判されてるのもそのためですし。例えばexportですよ。(後で知ったが、John SpicerもBerlin会議で似たようなことを言っている。議事録はここ)。何で委員会が標準化するのを、既存の、有効性が保証されているような物に限定しないんですかね。実際、そうやってSTLが出来たわけですしね。そうすれば、C++0xも、もう少し早く規格制定出来たんじゃないですかね。

Bjarne stroustrup

1996年の時点で、STLを「既存の、有効性が保証されている」ものだと考える人は、それほど多くいたとは思えんな。さらに、ライブラリの提案と、言語機能の提案は、だいぶ違うものだ。ライブラリの提案を予測するのは、比較的簡単だ。

フランクフルト会議で、ワシが指摘したのは、

  • ある人は、「商用実装がないものを標準化するべからず」と主張している。
  • 主要なベンダーは、標準規格なしで実装をしない(商用的に利点がある独自機能でない限り)

この問題を避ける方法としては、実証のための実験的な実装を提供することだ。ただこれは、議論を「十分に完全な実装とはどの程度か」と、「実験的実装の標準規格における準拠度はどのくらい正確か」といった事に変えるだけだ。

Conceptでは、実験的な実装であるConceptGCCと、実際に動くSTLがあった。ある人にとっては、これでは十分ではなかった。ただワシが思うに、多くの人が、実装の問題に気にしすぎていて、設計の問題には無頓着だった。設計と実装だけでは不十分だ。機能を使ったライブラリも必要だ。そのライブラリを使った、実際のプロジェクトも必要だ。まあ、それなら完璧だろうが、そんなに何年も実験ばかりしている暇はない。誰がそんな実験的な実装の上にプロジェクトや製品を作るというのか。仮に誰かがやったとしても、どうやって、そんな早い段階の実装上の経験を元に、微妙に違う標準規格を制定出来るのというのか。得られるのは、非互換な独自機能が増えていくことぐらいな物だ。C++98とC++0xの間の長い空白期間こそが、AppleやMicrosoftが独自「技術」を打ち出している理由なのだ。ただ、何も彼らに限った話ではない。企業というのは、業界のシェアと利益を追求するものなのだ。言語設計の汎用性の為にあるのではない。

従って、一般に新しいアイディアを評価するのは難しいし、広く使われている言語においてするのは、さらに困難である。不可能であるとは思わないが。ワシは大方は、実験的な実装で十分だと思う。たとえ完全ではなかったとしてもだ。機能を100%実装していないかもしれないし、他の機能との兼ね合いが十分ではないかもしれんし、パフォーマンスが最適化されていないかもしれん、デバッグ機能が欠けていたり、エラーメッセージが完全でないかもしれん等等。現実では、どの程度の実験が十分かどうかを判断しなければならんのだ。しかし、これはある機能に必要な物がすべて受け入れられるというわけではない。それに加えて必要なのは、規格の検証、単純性、完全性、汎用性、拡張性、ユーザビリティ、人に教えることが出来るかどうか。

多くの設計案を検証しなければならん。大抵の場合、ほんのわずかな規格設計の違いが、一般プログラマにとっての使いやすさを、遙かに変えるのだ。実装重視で見逃す事が多いのはここだ。ワシは「典型的な利用例」と、「重要な利用例」を集めて、多くの設計を試すことにしておる。WG21サイトにある、initializer listとinitializationに関する多くのペーパーが、このアプローチを実践しておる。さらに、ワシはチュートリアルを書き、生徒に複数の設計案を試させることにしておる。もちろん、他の言語機能との兼ね合いや、将来の拡張を検証することも必要だ。

もっと素早くて単純な「委員会による設計」以外の方法で、しかも金銭的援助が必要なく、企業の影響も受けないような規格設計の方法があると思うのは間違いだ。WG21では、「委員会による設計」を出来る限りなくそうとしておる。ほとんどの設計は個人個人で行われ、みんなの前にもっていって、改良していくのだ。それでうまくいくこともある。

John Spicerはフランクフルト会議でexportの問題を取り上げたし、ワシだって言った。他の連中も言っていたと思うがね。アレはいい例だ。しかし、アレから何かただひとつの教訓めいたものを引き出すことはできん。ワシがexportに関して言うことは、あまり手を広げすぎて、複数の技術案を取り入れることはよしたほうがいいということだな。むしろもっと明確な設計をするべきだ。

Danny Kalev

興味深いですね。C++98のtemplateのコンパイル方法として、現実的に使われているinclusion モデルとexportとが、Douglas Gregorがテキサスとインディアナと言っているのと同じ、二つの思想を一つの提案にまとめようとした結果なのですか。どうもそんな風に一緒くたにするのは、うまくいかないようですね。

Bjarne stroustrup

そうだ。exportの失敗は、templateのinclusion モデル と separate compilation モデルをひとつにまとめようとした事なのだ。ただし、君やみんなに知っておいていてもらいたい事は、当時、どちらの方法も実際に使われておったのだ。標準の方法がどうしても必要だったし、どちらのモデルも強く支持されておった。そういうわけで、折衷案は作りづらかった。こちらを立てればあちらが立たずとな。

省みるに、両方のモデルを絶対にサポートする必要がなかったために、ベンダーはinclusion モデルばかりを実装したんだろうな。EDGはexportを実装している。だが皆、主要なベンダーが実装し終わるまでは、いかに面倒であろうと、使いたがらないようだな。当時の私は、そういうことは考慮しておらんかったし、委員会が失敗したのも、明確な使い分けを考えてなかったことによるのだろう。ただ、委員会を責める前に、ちょっと考えてはくれんか。「今現在問題がある」のと、「将来問題になるかもしれない」のどちらを選ぶかということは、個人としては非常に難しい事なのだ。頭のいい連中同士で考えても難しい。

concept提案の根本的な違いを見分けるのはとても難しい事だ。この問題に気付いておらん者さえおる。難しいのは、「一体何が根本的な違いなのか」ということだ。当然、議論の多くはconcept mapに終始した。すでに示したように、concept mapはmappingの為だけに必要な機能だ。それ自体がすばらしいと考える者もおった。たとえ空で、何の型や操作も定義しないとしてもだ。フランクフルト以前のconceptの規格設計では、空のconcept mapを要求するようなconceptと(explicit concept)、mappingが必要でない限り、concept mapを必要としないconcept(automatic concept)があった。"simplifying the use of concepts"ペーパーでの論点は、concept mapは、曖昧性の解決に適してはおらんということだ。さらに、君の質問の答えとしてはだ。concept mapの正しい使い方に関する議論の結論は、標準化委員会による言語仕様に反映されるべきであり、conceptと曖昧解決の方法が提供されるべきだということだ。別案は、異なる思想のコードを一緒くたにすることであり、あまり使い勝手のいい物ではない。そこで正しい使い方ということに関して、激しい議論があった。

Danny Kalev

C++ユーザーはいい加減にしてくれよとか思ってるんじゃないですかね。この議論とかいい例ですし。conceptだけじゃないんですよ。ガベコレとかリフレクションとかGUIといった、超欲しい機能が、C++には絶対入りそうにないんですよね。その割には、実験的で難解な機能ばっかり議論されてるし。このコメントにあるように、もうC++ってオワッテルんですかね。言語自体が複雑すぎて、もうまともに改良出来なくなってるんじゃないですかね。

Bjarne stroustrup

その「超欲しい機能」とやらが何なのか、異論の多いことが問題なのだよ。ただ怒鳴るように主張だけして、まともに議論せんのだ。連中は分かってるつもりになっておるんだな。ワシは個人的にGCが好きで、C++0xにはGC ABIも入る。ただ残念ながら、標準GUIなどというものは無理だ。なぜなら、世に独自実装が多すぎるからな。多くの業界が、自前のGUIで囲い込みをしたいと思っておる。「実験的で難解」というのは、大抵、「俺の好きな別言語には無い、俺にとっては理解不可能な機能」を意味するのではないかね。かつては、クラス階層と仮想関数が、そういう機能だったな。

C++が終わってるなんてことはない。C++のマネ事をしている連中が言っているのだろう。

C++の標準化の方法は、確かに遅いし難しい。ただ、すでに言ったように、軽いノリの実験的な方法よりはマシだな。別の方法といえば、商業言語の進化は早い。なぜなら、カネもあるし、多数の環境を考慮しなくてもよいし、C++ほどの下位互換性を気にする必要はない。Visual Basicを覚えているかね。C++はVBほど早く進化しないとは、よく言われていたことだ。だが、C++は既存のコードをなるべく壊さないように進化してきたのだよ。ワシは未だに、崇高なベルラボみたいな研究室が、新しいアイディアを実験するには最適の場だと思っておるよ。

多くの現場は、いまだにC++98にすら追いついておらん。これは、他の言語に言えることだがな。

Danny Kalev

将来についてはどう思いますか。これからどうなるのですか。Technical Reportみたいな感じで、Conceptを後から追加するのでしょうか。あるいは、ド素人や、未だ悟りを得ていない愚痴なコーダ―にも使えるような、全く新しい規格を入れるような日が来るのでしょうか。conceptの廃止は、現行ドラフトにさらに大きな影響を与えるのでしょうか。

Bjarne stroustrup

やれやれ、偏見の多い誘導尋問みたいな質問だな。

まず第一に、C++0xは、すでに合意された改良をすべて取り入れて制定される。たとえば、concurrencyのサポート、標準ライブラリの改良と拡張、統一的な初期化、lambda、move semantics、汎用的な定数表現、等等。ワシの書いたC++0x FAQを読み給え。もはやこの段階では、大規模な変更は入らん。C++0xには重要な改良がたくさんある。いくつかは、すでにGCCやMicrosoftなどが実装しておる。新しい言語のように感じることだろうよ。

第二に、C++はすべての流行を追うような事はせん。実用の為に、ゆっくりと互換性を考えながら進化していくのだ。最先端機能満載の言語とか、極端に小さい言語とか、独自機能満載の言語といった、イカした言語が欲しいならば、他にいくらでもあるだろう。ただし、もしこの先何十年も使うプログラムの為に、十分に柔軟で、他よりパフォーマンスがよく、他に例を見ないほど汎用的で、どんなハードでも動くような言語がほしいなら、C++にし給え。

第三に、多くの人が、何らかの方法で、C++におけるConceptの良さと正しい利用方法を見つけるだろう。「後から追加」するなんてことは、誰も考えておらん。C++の標準化はそのようにはなされん。フランクフルト以前のConcept規格に、"simplifying the use of concepts"提案で改良を加えれば、ワシ的には、満足のいくものが、数ヶ月でできあがるだろう。だが、そんなことはせんよ。conceptを基本から考え直して、これまでに得られた経験は元にするとしても、ほとんどスクラッチから規格を書き直して、実験するだろう。まあ、五年単位の時間がかかるだろうな。だがしかし、やるよ。もっとも、conceptは他のアイディアに打ち勝つほどの利点を示さなければならんがな。もしリフレクションの方が優れているのではれば、代わりにそっちに注力することだろう。

conceptがTR(Technical Report)に向いているとは思えん。型システムに深く関わっているからな。TRというのは、それなしでもやっていけるほど分離できるものに対して行うのだ。型システムは、完全にやり遂げるか、何もしないか、の二者択一だ。

Danny Kalev

じゃ、C++に関しては、楽観的な見方をしてるんですね。

Bjarne stroustrup

ワシは昔も今も、注意深く楽観的に考えておる。ワシは、「ヒャッハーッ! 俺の言語、ツール、設計思想をもってすれば、おめーらのチンケな問題なんぞ全部解決してやれるぜ! 明日にでも世界を征服してやる! フゥハハハーハァー!」などといった楽観的な見方はしておらん。ワシはC++が、「ただ単に」、何百万人ものプログラマをサポートできて、多くの環境にソフトウェアの開発環境を提供し、高度なアプリケーションの開発に使われると言うだけで、十分満足だ。「ソフトウェアの環境」というのは、組み込み系だったり、システム開発だったり、リソースの制約が厳しい環境だったり、C++に最適な分野の事だ。C++0xは、C++98よりも、より良いツールになるだろう。

今としては、委員会はC++0xを小綺麗に包装して出荷せねばならん。xは16進数になるがね。そして実装が出そろう。いくつかの機能やライブラリは、すでに出回っておる。そこで、プログラマは委員会の多大な作業の恩恵を得られるというわけだ。

翻訳終了、疲れた。

まあ、色々と言いたいことはある。

当然、私には、「A::f()&&;とは一体どういう意味なのだ」とか、「std::move()は一体どうやって実装されているのだ」などといった疑問がわく。STLがどうやって実装されているのか知らずに使うなんて事はできない。実装というのは、アルゴリズム的ということもあるが、むしろ、もっと根本的な言語としてだ。だからこそ今の境遇があるわけだから、仕方がないことなのだが。

axiomについては、やはりあまり理解できない。なるほど、確かに公理を前提としたコードを書くし、仕様書にも書く。ただし、それをコンパイラがパース可能にしたところで、特に利点はない。公理の妥当性を検証する開発ツールなど、まず出ないだろう。とすれば、もっと人間の読みやすい形で書いた方がいい。それには、わざわざ新機能を付け加えるには及ばない。コメントという優れた文法が、すでに存在する。例えば、

auto concept LessThanComparable<typename T> : HasLess<T, T> {
        bool operator>(const T& a, const T& b) { return b < a; }
        bool operator<=(const T& a, const T& b) { return !(b < a); }
        bool operator>=(const T& a, const T& b) { return !(a < b); }
        axiom Consistency(T a, T b) {
                (a > b) == (b < a);
                (a <= b) == !(b < a);
                (a >= b) == !(a < b);
        }
        axiom Irreflexivity(T a) { (a < a) == false; }
        axiom Antisymmetry(T a, T b) {
        if (a < b)
                (b < a) == false;
        }
        axiom Transitivity(T a, T b, T c) {
                if (a < b && b < c)
                (a < c) == true;
        }
        axiom TransitivityOfEquivalence(T a, T b, T c) {
                if (!(a < b) && !(b < a) && !(b < c) && !(c < b))
                (!(a < c) && !(c < a)) == true;
        }
}

などと書いてあっても、少なくとも私には、どういう意味なのか、コードを一見しただけでは分からない。おそらく現実に使う際には、これを詳細に説明するコメントが、いちいち必要になるだろう。この文法自体が、コンパイラには特に使われる事もなく無視されるのであれば、そのコメントだけで十分ではないのか。

追記:Bjarne Stroustrupにジジイ口調は合わないという声を受信したので、Stroustrupの動画をいくつか見てみたが、確かに合わないと思った。

詐欺臭い燃費

GMの新型HV シボレー ボルト、燃費98km/リットルは本物か? | Response.

カタログスペックとかけなされることも多いが、ここまでくると詐欺臭くなってくる。

あらかじめ完全に充電されたバッテリーだけで64キロ走り、その後ガソリンで走って、トータルの燃費を出すとか。

久しぶりに爆笑した動画

犬が、犬が。どうやら急降下している模様。

2009-08-13

MS WordはXMLを使っているので特許侵害らしい

テキサス司法は、MS WordはワードプロセッシングとしてXMLを使っているので、i4iの持つ特許、5,787,449を侵害しており、MSに対し、あらゆる販売、広告を差し止めた上で、賠償として、出荷されたWordひとつあたり98ドル、総額2億ドルをi4iに支払うように命じたらしい。60日以内に反論しなければならないのだとか。

ワードプロセッシングソフトウェアがXMLを使うことにおいて、どんな特許が成立しうるのか、私の頭では理解できない。また、特許5,787,449に何が書いてあるのか、私の頭では理解できない。

総じてメリケンの特許の仕組みはよく分からん。

2009-08-12

cookieは消したから安心? まあ待ちねぇ待ちねぇ

You Deleted Your Cookies? Think Again | Epicenter | Wired.com

ブラウザがネイティブにサポートするcookieは消したとしても、Flash cookieがある。Flashは、今やほとんどのユーザーがインストールしている。なにしろ、Flashがなければ、Youtubeを初めとした動画サイトを見ることが出来ない。

ところが、Flashにも、cookie機能が備わっている。しかも、これは一サイトあたり100KBもの情報を格納できる太っ腹な機能だ。この機能を使っているサイトは非常に多い。

さて、ここで問題がひとつある。主要なブラウザはCookieやキャッシュなどの個人情報を削除するUIを提供している。ところが、たとえブラウザのcookieを消したとしても、多くのサイトで、Flash cookieにバックアップをとっておいて、cookieが見つからなければ、Flash cookieから復活させるような仕組みを実装している。これによって、cookieはゾンビのように復活するという寸法だ。

Flash CookieをFlash上から消す方法は元記事に載っていないが、一応はFlash上から提供されている。この手の記事を書いているのに、なぜこんなことを知っていないのか疑問だ。

既存のFlash cookieを消す方法。
Adobe - Flash Player : Settings Manager - Website Storage Settings panel

Flash cookieの使用を禁止する方法。
Adobe - Flash Player : Settings Manager - Global Storage Settings Panel

近いうちに、Flashを使わなくてもいい時代がやってくると確信している。少なくとも、あと数年すれば、簡単なFlashは、video、audio、canvasに置き換えられるだろう。そのためには、IEをこの業界から締め出す必要があることはもちろんだが。

文字と文化は切り離せないというお話

絵文字が開いてしまった「パンドラの箱」第5回--絵文字と日本マンガの親密な関係:コラム - CNET Japan

まとめ、Google提案に対して、アイルランド・ドイツ勢が、より汎用的な提案をだした。ところが、連中はマンガ文化を無視しているので、意味が変わってしまっている。

文字と文化は切り離せないのだろう。

文字文化と言えば、HTML5でも、未だにガチガチの物理要素であるbとiを残すらしい。廃止するべきである。strongやsmallのようなものは、重要度や注釈を表現する要素として解釈でき、どのように修飾するかは、まだ裁量の余地があるのだけれど、bやiには、余地などない。HTML5ドラフトでは、言い訳がましく、「iは通常とは異なった雰囲気を演出する」であるとか、「bは重要度を特別に変えることなく、その文脈の中で少し異なった意味を持つ」であるとか、規定しているが、無駄な努力である。

たまに、日本語に対してboldやitalic表示を使っているサイトを見かけるが、やめるべきである。漢字がつぶれてしまって読みにくいことこの上ない。

そういえば、小説でも、一時期、フォントフェイスやウェイトを変えるなどという、見ぐるしい修飾の流行った時期があった。世に一流の聞こえある作家達も、こぞってそういう修飾を使っていた。馬鹿げたことである。たったの数十文字しかないラテンアルファベットならともかく、日常的に使うだけで何千文字もある日本語は、そんな修飾を使っても読みにくくなるだけだ。

らばQの内側事情

小さな編集部。3人で運営するらばQのそれぞれの役割と運営術*ホームページを作る人のネタ帳

らばQというブログ形式のサイトがある。私の印象では、現れて、すぐ人気になったサイトだと思う。こういう面白い情報を延々と紹介していくサイトは、ブログが主流になる以前からもあった。そのなごりか、いまだにATOM/RSSも出してないようなニュースサイトが、かなりのPV数を誇っていたりする。

らばQを見た時、これは個人の仕事じゃないと思った。ただ、何人で回しているのかということを考えた時、5人か10人くらいじゃないかと、漠然と考えていた。それが、たったの3人で運営しているらしい。

まあしかし、あまり儲かる仕事ではないだろうな。

日本ではWeird Al Yankovicは生まれない

クリプトンさんがミイラになりつつある件 : ひろゆき@オープンSNS

どうやってクリプトンが権利侵害を申し立てられるんだというお話。

まあ、実際には、初音ミクが牢屋に入っているという所から、クリプトンの「利用規約」とやらに反していると判断したのだろう。ただ、あの利用規約、法的にどうなのかと思うのだが。

替え歌だから著作権を侵害しているという論争が生まれるのは、日本ならではのことか。嗚呼、パロディの権利が認められていない日本では、Weird Al Yankovicのような優れた歌手は生まれない。

まあ、Al Yankovicは、いちいち許可とってるらしいが。

2009-08-11

運動の成果

運動を始めて早四ヶ月、中学生時代の、サッカーをやっていた頃の体力が、少し戻ってきた気がする。体も四ヶ月前に比べて、少し引き締まったような感じがする。

問題は、太ももが太いままということだ。

これは異朝にも例あり。昔者、蜀の劉備、未だ劉表の食客たりし時、厠へ行くとて、宴会の座より起ちて行きたる程に、己の髀肉の肥えたるを見て、落胆したりけるとぞ。

毎日ジョギングしているのだが、どうも太ももの太さは変わらない。そもそも、昔も、あまり細い方ではなかったのだが。

2009-08-10

The importance of punctuations

I had to help my uncle, Jack, off a horse.

I had to help my uncle jack off a horse.

A woman, without her man, is nothing.

A woman: without her, man is nothing.

Stroustrupは詩人過ぎて困る。

Bjarne Stroustrup Expounds on Concepts and the Future of C++

The committee operates according to ISO rules. Those are quite ponderous and biased in favor of not upsetting status quo.

委員会はISOのルールに従って運営されている。堅苦しくて、保守的である。

ハッキリいって禿はラテン語使いすぎ。

ponderousなどというのは、辞書で調べればすぐに意味が分かるのだが、"biased in favor of not upsetting status quo"なんぞは、個々の単語だけではさっぱり意味が取れなかった。そもそも、status quoが辞書的な説明では、いまいち理解できない。結局、ネイティブに意味を聞いた。

一応、気になる人の為に、文面を簡単にすると、"they cover too much detail over everything, and they prefer not to change anything too much." となる。直訳すると、「やたらと細かく規定したがるし、何も変更しないことを好む」というような意味か。

だいたい、status quoだけで意味は足りるのに、わざわざ二重否定するのはどうなんだ。「ずんばあらず」じゃあるまいし。確かに、漢文を読んでいると頻出する表現ではあるが。

2009-08-09

鴨川納涼

常の如く、鴨川沿いをジョギングしていた所、鴨川納涼とかいうのが、今夜開かれるらしい。面白そうなので物見に行こうと思う。

追記:尺八教室なる物があったので、尺八を吹いてきた。しかし、音が出ない。尺八を吹くのは難しい。

2009-08-08

愚管抄

宇治拾遺物語を読み終えたので、愚管抄を読むことにした。

愚管抄の作者である慈円の評価できることは、愚管抄を仮名文字で書いたことだ。そのため、実に分かりやすい。

ただ、世間的には、あまり高い評価を受けていない。歴史的には、当時の朝廷から幕府へと、政権が移っていく激動の世の中のことを書いてあるので、興味深いのだが、文学的には、第一級とは言い難い。平家物語は、ある意味分かりやすい文学である。教訓的には、盛者必衰の理ぐらいしか言っていない。盛者必衰は、現代人でも、共感できる。ところが、愚管抄には、仏教的な道理というものが出てくる。というのも、どうも慈円は物事をすべて道理で考えていたらしく、あらゆる出来事が道理をもって評価されている。現代からしてみれば、あまり共感できる部分はない。これが、平家物語が評価され、愚管抄が評価されなかった理由なのだろう。慈円は平家物語を、事実を伝えていないとけなしているが、愚管抄も、事実はあるにせよ、その評価方法が極端すぎるので、どうも良い物とは言い難い。

陶器まつり

8月7日から10日まで、五条坂で陶器まつりが行われている。これは、名前の通り、陶器の露天が道を連なるものだ。場所は、五条川端通りから東大寺通りまでの間の、いわゆる五条坂だ。

陶器に興味はないが、せっかくなので冷やかしに行ってみた所、なかなか面白かった。

一口に陶器と言っても千差万別で、いかにも上品そうな焼き物もあれば、野性感あふれるゴツゴツとした作りの物もあった。

個人的に気になったのは、箸置きだ。これがなかなか面白く、猫とか犬をかたどったかわいらしい箸置きがたくさんあった。

助六と曾我五郎の人形があり、これも陶器なのかとしげしげと見つめていたら、残念ながら、樹脂製であった。

そのほか、陶器に紛れて、二束三文の怪しげな雑多の物品が売られていり、かき氷やたこ焼き 金魚すくいといった、おなじみのテキ屋もあった。

Google先生の不思議な翻訳

Google Translate: so, please let us know.

Translation Partyで遊んでいたら見つけた。不思議な翻訳だ。

Bjarne Stroustrup、Conceptについて語る

Page 1: Concepts: Disappointment Without Defeat
Page 2: Concept Awareness
Page 3: Do We Still Need Concepts?
Page 4: Commitees and Standardization

あまりに長いので翻訳する気にはならないが、これも全C++プログラマが読むべき。

2009-08-07

C++規格の、freestandingの意味

freestandingという概念は、C++98の頃から存在する。ところが、この概念は、一般のC++プログラマーには、あまりなじみがないと思う。そこで、この意味と意義について解説してみようと思う。

freestandingとは何かということを説明する前に、C++が使われている状況について説明する必要がある。

C++は、非常に広く使われている。OSやドライバといった低級な部分から、エンドユーザーが実際に使うGUIのソフトウェアまで、幅広く使われている。携帯電話などにも、C++は使われている。

携帯電話やリアルタイム性が要求される場面など、リソースが極端に限られている環境では、通常の標準ライブラリが適さない場合も多い。そういう環境では、C++の言語自体は実装していても、ライブラリは、完全に提供していないこともある。そういう場合においても、C++の言語を実装する上で、最低限必要な条件を決めておこうというのが、freestandingの意図だ。

ここでは、freestanding規格のうち、ヘッダーについて更に詳しく説明する。

C/C++というのは、言語とライブラリの間の依存性が、極力少なくなるように考えられている言語である。なぜなら、環境によって標準ライブラリが適さない場合もあるのからだ。この思想があるからこそ、現在、リッチなクライアントアプリケーションから、組み込み系まで、幅広くC++が使われているのである。

ところが、やはり言語としては、ライブラリから完全に独立するということは難しい。

たとえばnewを実装するには、一連のnew 演算子などが必要であるし、例外クラスも必要である。typeidが返すのは、type_infoというクラスだ。

これを考えれば、言語をライブラリから完全に引き離すのは、仮に出来たとしても、面倒な事が多い。しかし、C++は先にも述べたように、言語とライブラリ間の依存性を、極端に気にする思想でもって設計された言語である。そこで、規格にも、最低限の実装にはどんなヘッダーが必要か、具体的に書かれているのである。

なぜこんな事を解説しているかというと、n2932 Fixing freestanding: iteration 2.2をレビューする必要があるからだ。この前提知識があれば、n2932が理解しやすくなると思う。

n2932自体には、プログラマが直接気にしなければならないことは、ほとんど書かれていない。ただ、type_indexを使う際には、<typeindex>ヘッダーをincludeしなければならないという変更がある。これだけは抑えておいた方がいい

Twitter、特許違反として訴えられる

BBC NEWS | Technology | US firm sues Twitter over patents

メリケンの国の特許の仕組みはおかしいんじゃないかと、常に思う。

下駄

以前から、下駄が欲しいと思っていた。しかし、わざわざ買いに行くほどでもなかったので、いつまでたっても下駄を履くことはなかった。

この間、一年ほど履いていた雪駄が壊れたので、雪駄を買うついでに、下駄も買うことにした。寺町に、雪駄と下駄ぐらいしか売っていない店がある。

さて、下駄の値段だが、ピンからキリまでである。もちろん、雪駄だって、牛革使用だとか、手で編み上げているだとか、色々と高い物はある。かかと部分に無意味に金具が付いていて、歩くとチャラチャラ音が鳴るような、粋な雪駄は売っていないにせよ、高い物はある。しかし、下駄は、また違った基準で値段が付けられてる。

まず、下駄の大部分を占める木材の値段がある。そして一番重要なのが、鼻緒だ。鼻緒の良し悪しで下駄の値段が左右されるらしい。

肝心の歩き具合だが、すぐになれた。アスファルトとコンクリートだらけの、現代の日本の地面においては、少々歩きづらいかも知れないが。

Douglas Gregor、フランクフルト会議について語る

What Happened in Frankfurt? « C++Next

これは全C++0xプログラマが読むべきだと思う。悲しい話だ。

フランクフルトで何があったのか?

C++0xの発展に興味のある人は、もうニュースを聞いただろうと思う。ISO C++委員会は、2009年7月のフランクフルト会議で、C++0xのドラフトから、Conceptを外すことを、投票で決めた。Conceptは、C++0xの重要な機能で、その削除は、かなりショックを与えたことだろう。ここでは、私はConceptをC++0xに入れるにあたってなされた努力と、結果的に失敗した理由を、語ろうと思う。

Conceptの歴史

C++プログラマは、常に、もっとマシにtemplateを使いたいと考えていた。契約的(原語:constraints)なC++のtemplateは、少なくとも、Bjarne StroustrupのThe Design and Evolution of C++(15.4を参照のこと)(訳注:邦題、C++の設計と進化)の頃からあった。Jeremy Siek と Andrew Lumsdaine はこの契約的なチェック機構を、conceptへと拡張し、根本的には、templateの定義を型チェックするように振る舞うことを示した。(Siek2000) 2003年、Bjarne StroustrupとGabriel Dos Reisは、一連の提案書を書き(N1510N1522N1536)、C++言語において、conceptがどのように表現できるかということを、考察した。

私自身のconceptへの関わりは、2005年の1月に、Concepts for C++0xを共著したことから始まった。これは、インディアナ提案と呼ばれているものだ。そのすぐ後に、Bjarne Stroustrup と Gabriel Dos Reis は、A Concept Design (Rev. 1)という提案を著わした。これは、テキサス提案と呼ばれることになった。Conceptが始めてC++委員会で議論されたのは、2005年の4月のノルウェイで行われたリレハンメル会議においてだった。インディアナ提案とテキサス提案は、明らかに、設計思想を異にする物であった。もちろん、お互いの主張は色々あったが、最も根本的な違いは、如何にして、conceptにおいて、データとしての型にmatchingさせるかということであった。テキサス提案は、すべてにおいて、暗黙的な(自動的な)matching(例えば、現行規格のauto conceptのようなもの)を好んだ。インディアナ提案は、すべてにおいて、明示的に妥当性を示されており、remapping可能(例えば、現行規格のconcept mapのようなもの)であるものを好んだ。

リレハンメル後、私は六ヶ月かけて、ConceptGCCを実装した。最初にして唯一の、conceptを実装している実験的なコンパイラだ。このコンパイラは実際の実装を提供することを意図していた。(訳注:この一文、原文では、proof-of-conceptとかけているらしい) ConceptGCCでの経験は、インディアナ提案をすばらしいほどに改良できた。私は2005年10月の会議で、ConceptGCCを披露した。委員会の反応は、おおむね良好だった。しかし、一部の委員は、二つの提案が著しくかけ離れていくのを危惧した。(訳注:インディアナ提案とテキサス提案の)著者達は、協力して、統合した提案を書き始めた。我々は多くの会議をして、細部を洗い出し、最終的に、最初の統合された提案を、2006年6月に発表した。同時に、ConceptGCCの標準ライブラリの開発が進められ、我々は、最初の提案書である、標準ライブラリにおけるConcept(N2036-N2041を参照されたし)を書き上げた。

我々は委員会外で何度か会議を行った。会議毎に、さらなる議論と、それに伴う提案書の変更がなされた。最大の変更は、or constraintsの削減scoped concept mapの導入、forwarding functionの省略、だ。またこの時点で、私は最初のドラフトである、conceptの規格書における文面を書き上げた。これは後に、言語とライブラリの両方で、幾多も改訂されていくことになる。

2008年9月のサンフランシスコ会議にて、conceptはついに、ワーキングペーパーに取り込まれ、最初のC++0x candidate draft (CD1)に入った。つまり、C++0xのリリース候補のドラフトに、第14版にして、取り込まれたのだ。これは、コア言語とかなりの分量のC++0x標準ライブラリを占める

フランクフルトまで

サンフランシスコ会議から6,7ヶ月たち、標準規格と標準ライブラリの文面に、様々な改良が加えられていった。フランクフルト会議が近づくにつれて、ある二つの問題が持ち上がった。実装経験に対する憂慮と、統合されたconcept規格に対する思想の相違である。

実装経験への憂慮というのは、ConceptGCCの不完全さである。例えば、コンパイルのパフォーマンスが低いことや、高度な機能に欠けていること(scoped concept map、associated template)だ。委員会の委員達は、conceptベースの標準ライブラリを評価するのに、製品レベルの品質を持つ実装が無いという現状では、言語とライブラリのconcept規格には、未だ多くの欠陥が残っているであろうことを憂慮した。これらの欠陥は、良くて、C++0x規格の発行を更に遅らせるし、最悪の場合、欠陥だらけの規格を世に出してしまうことになる。

同時に、conceptに関する、多数の、白熱した議論が委員会のメーリングリストでなされていた。多くは、現行規格の使いにくさの問題である。例えば、場合によっては、ライブラリのconstrained templateの要求を満たすためだけに、ユーザーは空っぽのconcept mapを書かなければならない。ユーザーはそのようなconcept mapを、文法上のゴミであると看過するだろう。議論はBjarne Stroustrupのペーパー、Simplifying the use of conceptsに集約された。これらの設計に対する不安は、インディアナとテキサスの思想が、今以て、いかに大きな隔たりであったかを物語っている。あげく、Stroustrup博士のペーパーは、所謂、明示的なconceptを削減しようとまで提案していた。これは2005年からの、conceptの根本的な問題であり、そもそもの初めからの問題だったのに。

フランクフルトにての投票

C++委員会は、フランクフルト会議の初めから、およそ半日かけて、conceptの境遇について議論した。Stroustrup博士は、次の三つの選択について、投票をさせた。

  1. C++0xの現行規格のConceptを維持する。
  2. ”Simplifying the use of concepts”の提案を受け入れて、C++0xにconceptを存続させる。
  3. C++0xからconceptを削除する。

疲れ切った委員会の委員達と共に、私は、concept削除に投票した。何故ならば、言語の未来を考えた時、C++0xとconceptにとって最良の選択は、削除することであろうと思ったからだ。

個人的には、現行規格を通すべきだと思っている。これこそが根本的に正しい設計だと信じている。しかしながら、現時点においては、合意が得られていないことは明らかである。広くC++業界に受け入れられる以前に、我々の中でも合意に達しなければならない。就中、実装経験に関する憂慮は、当然のことである。それだけの故を以て、C++0xからconceptを削除するに足る。

第二の選択である、設計に大幅な変更を加えて、C++0xをconceptと共に発行することは、到底支持できない。開発の、この期に及んで、かかる大きな変更をするのは、極めて危険である。この場合、実装経験がないこと、使用経験がないこと、新設計が動くかどうかを検証する為の技術力が足りない。ConceptGCCですら、十分な実装経験ではないと考える人がいるのだ。変更した設計のまともな実装など、まず出ることはない。そもそも、この問題に関する思想の相違の経緯を考えれば、我々が提案された変更に合意できるわけがない。

他の選択肢もあった。例えば、C++0xを、さらに数年遅らせて、合意を得るだとかだ。しかし、そんな延期は、受け入れられるわけがない。conceptをC++0xから削除するのが、もっともマシな選択肢だったのだ。一方、委員会はconceptに賛成であり、将来、まともな提案をひっさげて、また議論することだろう。次の記事では、この失敗から学んだ事と、将来の方法について語ろうと思う。

C++0xのすんばらしいSFINAE

 template<typename C> auto begin(C& c) -> decltype(c.begin());
template<typename C> auto begin(const C& c) -> decltype(c.begin());

上記の関数は、cがbegin()メンバ関数を持っているか、const修飾されたbegin()メンバ関数を持っているかどうかで、SFINAEによって適切なOverload Resolutionがなされるらしい。知らなかった。

ということはだ。この新しい関数宣言とdecltypeのテクニックを使えば、型がある名前のメンバ変数やメンバ関数を持っているかどうかを調べるメタ関数が、簡単にかけることになる。

#include <type_traits>

// T型がhogeというメンバ変数を持っているかどうかを判別するメタ関数
template < typename T >
struct has_mem_hoge
{
private :

    template < typename U >
    [] check() -> decltype(reinterpret_cast<U *>(nullptr)->hoge, std::true_type) ;
    template < typename U >
    std::false_type check() ;

public :
    static const bool value = std::is_same< check<T>(), std::true_type >::value ;
} ;

// T型がhoge()というメンバ変数を持っているかどうか判別するメタ関数
template < typename T >
struct has_memfun_hoge
{
private :

    template < typename U >
    [] check() -> decltype(reinterpret_cast<U *>(nullptr)->hoge(), std::true_type) ;
    template < typename U >
    std::false_type check() ;

public :
    static const bool value = std::is_same< check<T>(), std::true_type >::value ;
} ;

ところで、Variadic Templateは、いまいち分かっていないのだが、もし上記のhas_memfun_hogeを、任意の数の引数をもつメンバ関数hoge()に対応させるには、こんな風に書けばいいのだろうか。

template < typename T >
struct has_memfun_hoge
{
private :

    template < typename U, typename ... Types>
    [] check() -> decltype(reinterpret_cast<U *>(nullptr)->hoge(Types ... args), std::true_type) ;
    template < typename U >
    std::false_type check() ;

public :
    static const bool value = std::is_same< check<T>(), std::true_type >::value ;
} ;

あと、良く考えたら、これでもいいよね。

//面倒
std::is_same< check<T>(), std::true_type >::value ;
//簡単
decltype( check<T>() )::value

2009-08-06

またXSS脆弱性か!

Googleに超べんりな隠しページが - ぼくはまちちゃん!(Hatena)

リンク先の先、注意。どうやらGoogleの求人ページにXSSに対する脆弱性があったもよう。googleのドメインの中で、こんなスクリプトが実行されてしまう。

Googleの馬鹿げた買い物

GoogleがOn2 Technologyを買収したそうだが、無駄な買い物だといわざるを得ない。VP6、VP7、VP8の画質は、H.264に比べて、明らかに劣っている。しかも、H.264には様々なエンコーダー、デコーダーがある中で、VPに関しては、On2公式のみ。しかもエンコーダーは堪えられないほど遅いと来ている。

On2が所有する動画関係の特許が欲しいならともかく、VP8の為に買収するのは、カネの浪費としか思えない。

2009-08-05

IE6 no moreなる動きがあるらしい

IE6 No More - Home

このブログでもすでに似たようなことをしているが(そもそも、私の基準ではIE8もあまりよろしくないが)、そろそろこういう直接的な働きかけが必要だ。現状を変えるには、ほぼすべてのユーザーというのは、ソフトウェアの定期的なアップデートやセキュリティパッチを当てないという、救いようのない人間であると認識することがまず第一である。

この発想力はどこから来るんだろう

はてなスターをもらう簡単な方法 - ぼくはまちちゃん!(Hatena)

1. 巨大な透過gif画像を用意

そんな手があったか。この発想はどこから来るのか分からない。そしてリンク先の記事のはてなスターがリロードするたびに増えているという自己言及的なおもしろさ。

operaがZii EGGで使われる事に関するプレスリリース

Opera inside Zii EGG: Opera Devices Selected by ZiiLABS to power it's latest platform

Opera側から、プレスリリースがでてる。

それにしても気になるな。Zii EGG。本当に1080pのH.264動画を再生できるんだろうか。

Flash Lite置き換えとな

「HTML 5にはまだ多くの課題がある」――Adobe社エバンジェリストが優位性を強調 - 家電・PC - Tech-On!

Adobe社は組織を改編し,組み込み向けFlashである「Flash Lite」を原則として置き換え,組み込み向けも次のメジャー版から「Flash Player 10」に統一しようとしている

なぬ。本物のFlashが来るとな。しかし、携帯で専用ハードなしにH.264のデコードは難しいんじゃないかなぁ。それに、時代はやはりHTML5だよね。

2009-08-04

最高に次世代で革命的で最先端な受賞作としての宣伝文句(当社比)

10 Words I Would Love To See Banned From Press Releases

まあ、誰もが思っていることだが、英文が結構面白かったので紹介する次第。訳しても面白い感じがでないので、訳さないが、つかみだけ。

LEADING / LEADER(先進的)

みんな先進的なら、それは誰も先進的じゃないって事だろ。PRの連中よ。こんな言葉つかうのはやめとけ。

BEST / MOST / FASTEST / LARGEST / BIGGEST / etc.(最高、最大、最速、最強、等等)

INNOVATIVE / INNOVATION(革新的)

実に無意味な言葉だ。だいたい、年にいくつ、真に革新的だと言える製品が出てるよ。革新的って謳っておきながら、実際なんか違いはあったか。まあ、お前さんが、あらゆるガンの治療方法を確立するまでは、今後一切、この言葉を使うのはやめておけ。それこそ革新的って奴だな。

REVOLUTIONARY(革命的)

プレスリリースで使うにゃ最悪の言葉だな。一体どうやったらお前んとこの製品が、人民をして、家を飛び出してデモに向かわせ、反政府活動をさせ、暴徒と化せしめ…… おっとすまんすまん。世界を変えるって意味じゃなくて、お前んとこの会社が、業界を変えるって意味だっけ。まあ、無理な話だ。

AWARD-WINNING(受賞作)

なあ、受賞にゃ何の意味も無いんだぜ。ノーベル賞とかピューリッツァー賞とかは、また別だがな。パーティでみんなに、俺は先週、ホモ・サピエンス・サピエンスと寝たなんて言いふらしてるのと何ら変わりゃしねぇ。だいたい、お前さんとこの製品を評価してくれる人を探してるなんて、悲しいことじゃないかね。

DISRUPTIVE / DISRUPTION(型破り、掟破り)

型破りの製品なんてホントにホントにホントに少ないぜ。本当にそれが型破りだったとしてもだ。業界全体を変えるには何年もかかるぜ。一夜にして変わるなんてこたぁない。だいたい、本当に型破りの製品だったとしたら、わざわざ宣伝するまでもないだろ。

CUTTING / BLEEDING EDGE(最先端)

NEXT-GENERATION(次世代)

ハッキリ言って使いすぎだ。製品の改良版なら、そうと言やぁいいじゃねーか。一体、新製品を次世代と呼ぶことで、俺に何を伝えたいのか、さっぱり分からん。あまりに最新複雑すぎて、俺みたいなオールドタイプにゃ使いこなせないシロモノなのか。お前の前の製品があまりにクソすぎて、世代をひとつすっ飛ばさにゃまともにならんほどだったのか。

携帯

いい加減にまともなブラウザを積んだ携帯を買おうかとおもって、色々調べてみた。

実際に現物を見なければ分からないとも思い、店頭にも行ってみた。

結論としては、QWERTY配列のキーボートを積んだ携帯は、実際には、あまり魅力的ではないと言うことだった。各ベンダーの努力は認めるが、やはりあの大きさでは、二本の親指で押すしかないし、押し加減も硬すぎるし、確かに押せたかどうかも、分かりづらい。あれなら、iPhoneのような全面タッチパネルの携帯の方がまだマシだ。

はこすべからず

大昔の話である。その頃は、不吉な方角であるとか、不吉な日時であるとかいった馬鹿げた迷信が、広く信じられておった。例えば、方違へといって、ある人のがり行くとて、方角が不吉なれば、まず逆方向へ行き、偶々その方角にある、よその家に泊まるという、不思議な習慣があった。あるいは、物忌みといって、今日は不吉だから、家に閉じこもって人と会わぬ、などという日もあった。およそこのような幼稚な迷信が、守るべき作法として信じられていた時代の話である。

さる屋敷に、嫁いできたばかりの生女房がいた。まだ若く、作法をよく知らなかった。そこでこの生女房は、紙を求めて、ある若い僧に、数々の作法、すなわち吉凶を書き記した、仮名暦を頼んだ。仮名暦とは、仮名文字で書かれた暦のことである。普通、暦をはじめ、この頃の文章というのは漢文で書かれるものであった。仮名は、ある有名なオカマ一人を除いて、基本的に女が使う物であった。

若い僧は、「やすき事」とて、二つ返事で請けおうた。この生女房の第一の失敗は、若い僧に頼んだことである。若いというのはすばらしいことであるが、得てして不真面目に走りやすいものである。この僧も、御多分に洩れず、そういう種類の若さを備えた青年であった。

さて、できあがった暦をつらつら見るに、初めは、真面目な暦であった。無論、現代に生きる読者諸君にとっては、迷信にまみれた馬鹿げた暦であると看過するであろうことは間違いない。神ほとけに祈る日、不吉なので家に閉じこもる日、等等。これを今日の価値観を持って見るにはあたらない。何しろこれは、大昔の話だからだ。

ところが、終わりの方になると、坊主も茶目っ気をだしたか、筆の運びが、やや怪しくなってきた。物くはぬ日、逆に、よく食ふ日などが記されていた。女房も不思議には思ったが、所詮、こういうものは形から入らねばならぬので、こういうものであろうと一人納得していた。

ところで、その茶目っ気の一つに、はこすべからずなんどと書かれた日があった。はことは何か。これは便器のことである。当時、身分ある女性は、用を足すのに箱を用いた。催した際には、この箱の中に用を足し、しかる後に、賤の女の童にでも命じて、捨てさせに行くのである。中には、この箱の中にまで気を使って、香木を入れていた自意識過剰な女もいるそうだが、それはまた別の話である。ともかく、はこすべからずとは、用を足すべからずという意味であった。

さて、この女房が、暦通りに作法を務めているうちに、とうとう、はこすべからざるの日がやってきた。その日は行いすましていたけれども、所詮は人間である。用を足さずにおれるわけがない。二日、三日とたつうちに、とうとう堪えきれず、左右の手で尻をかかえて、「いかにせん、いかにせん」とよぢりすぢりする程に……

その後の具体的な話は、遺憾ながら曖昧である。あるは、我慢はできたものの、発狂したと主張し、あるは、結局漏らしたとも主張している。しかし、これらの違いは、当の悲惨な女房からしてみれば、些細なことである。

この物語を笑う者に語を寄す。この仮名暦は、現代にも、なお多く存するのである。

2009-08-03

予備自補:食事について

食事は、時間が決まっていて、その時間内に食堂に行って、食べなければならない。

食を論ずるにあたって、まず問題にされるのが、味だ。といっても、私は美食家ではないので、味の良し悪しは、よく分からない。味については、別に悪くはないと思う。少なくとも、毎日違う物がでるので、飽きるということもないだろう。ただ、かなりいろんなものがでるので、好き嫌いがあるような人や、アレルギーのある人には、向かないだろうと思う。

私が特に気に入ったのは、昼夕は、必ず麦飯がでることだ。もちろん、白米のみもあって、選ぶことができるが、私は常に麦飯を盛りつけた。麦飯はうまい。森林太郎の亡霊はお呼びではない。

土日は、朝食がパンや弁当になったりする。また、調理場の点検などで、弁当になることもある。

次に重要なのは量だ。これに関しては、申し分ないと言っていいだろう。むしろ、常人には多すぎる。一食千キロカロリー超えはざらである。相当な運動をしていないと、太ってしまうだろう。予備自補のAB課程では、それほど激しい運動はしなかった。しかし、炎天下のなかの基本教練は、なかなかに腹の減る訓練であったので、私は残さずに平らげた。体格にもよるが、一般に言って、女性には、やや多すぎるかもしれないとも思った。

実は、本当の問題は、味や量ではない。時間だ。食べる時間は、15分もあればいい方である。これが一番の不満となるだろう。

一つ分からないことがある。それは、「喫食きっしょく」という自衛隊用語である。喫という字は、もちろん動詞として、ものを食べる、飲むという意味につかうことができるのだが、手持ちの辞書では、口語によく用いられるとある。食という字は、こういう風に使えるのだろうか。「君子無終食之間違仁」などという例もあるので、まあ、できるのかも知れない。それにしても、自衛隊以外で耳にしない言葉だ。書見という言葉を、漢語ではないと一笑した森林太郎は、一体何を思うのだろうか。

最高に疲れた失態

GMailのパスワードを忘れかけていた。

そういえば、少し前に、より長い物に変更したのだった。なんとか思い出すことができたが、精神的に激しく疲れた。

それにしても、危ない所だった。もし、今使っているgoogleのアカウントが使えなくなったら、被害は単にメールに留まらない。このブログも更新できなくなるし、200を越えるsubscriptionを登録しているGoogle Readerも使えなくなる。そのほか、GMailで登録している他のWebサービスも、軒並み危なくなる。本当に危ない所だった。

2009-08-02

予備自補:頭髪について

坊主頭の人は、注意を要する。

私は、自衛隊の新隊員といえば、全員、強制的に頭を丸刈りにするだろうと思っていた。予備自補はともかく、少なくとも常備はそうだろうと思っていた。これは、数十年前は事実だったそうだが、今は違うらしい。むしろ、丸刈りはあまり好ましくないとまでされている。自衛隊員が訓練中に怪我をすると、色々と面倒で費用もかかる。現在では、怪我防止のため、あるいは怪我の程度を抑えるため、多少の頭髪のあることが望ましいとされている。海自となるともっと極端で、丸刈りは禁止されているらしい。思うに、船というのは狭いし出っ張っている部分も多く、頭をぶつけやすいのも、関係しているのだろう。

実際、基幹隊員の中にも、坊主頭にしているものは、極めて少ない。側頭部をそっていても、頭頂部には髪を残している。丸刈りにしている人も、半分ぐらいは、すでに頭頂部が禿げ上がっているので、ついでに側頭部も剃っているといった具合だ。

というわけで、あまりに長い髪は好ましくないが、坊主頭も、好ましくはないのだ。

とはいえ、世の中には、常に坊主頭でないと落ち着かない人種も存在する。同類として、その気持ちはよく分かる。しかし、不都合がある。もし坊主頭で訓練に参加したいと思うならば、この不都合を受け入れなければならない。

中帽と呼ばれるヘルメットがある。これは通気穴が存在しないヘルメットである。執銃時の基本教練では、必ずこの中帽を被らなければならない。頭髪のある者は、暑苦しい程度で済むのだが、丸刈りにしている者にとっては、中帽は危険である。革ひもが当たって痛いこと、身をかがめただけで簡単にずれてしまうことなどの不都合もあるが、最大の不都合は、熱中症である。丸刈りにしている者は、中帽を被ると、熱中症にやられる。おそらくは、髪がないことにより、汗が流れ落ちて、その場に留まらないからだろう。

熱中症の兆候としては、非常に眠たくなることだ。私の場合、訓練を開始して30分足らずで、立っているのもつらいほど眠たくなった。あまりにひどかったので休憩を与えられたほどだ。最初、これが理解できなかった。予備自補は、訓練として8時間の睡眠を義務づけられている。2200から0600までの間は、トイレの外は、ベッドの中に入っていなければならない。睡眠は十分にとっているはずだ。それが、たった30分、それも、小銃を持ち上げたり置いたりする程度の運動で、ここまで眠くなるはずがない。頭髪を有する者に訊ねても、「確かに暑いがそこまでのことはないだろう」という。しかも、私の頭を指さして、「その坊主頭なら俺より楽だろう」というではないか。果たして私はそこまで貧弱なのだろうか。

否、私のように丸刈りにしている者は、皆同様の症状を訴えるのだ。これは髪がない為である。我々は売店へ走り、争いてヘルメット用のキャップを買った。速乾性が謳われているキャップだ。800円した。このキャップをあらかじめ水で濡らしておいて被り、その上から中帽を被る。革ひもが頭に当たって痛くなることもなく、中帽がずれることもなく、しかも嘘のように熱中症にかからなくなった。

売店で800円もするキャップを買ったのは、髪が極端に短い者だけだった。このことからも、髪の長い者にとっては、わざわざキャップを買うほど切実な問題ではなかったのだと言うことが伺える。

坊主頭に固執する人間は、かならず速乾性に優れたヘルメット用のキャップを買うべきである。

2009-08-01

予備自衛官補:売店について

はじめに

予備自衛官補の訓練内容を、どこまで公開していいのか、地本の人と話し合ってきた。基本的には、大抵のことは公開してもいいらしい。例えば、営内の売店では何を売っているかとか、何時に起きて何時に飯を食べて何時に消灯してなどの類は、問題がないそうだ。また、パンフレットに書いてあるような内容は、まったく問題ないとのことだった。ただしやはり、銃に関しては、やめた方がよいと言われた。実際、ググってみても、小銃の分解結合の詳しい手順などの情報は、まったくヒットしない。無論、そんな情報を書くつもりはないが、次の訓練までの一ヶ月間、イメージトレーニングとメモだけで分解結合の手順を忘れないようにしなければならないのは、なかなか大変だ。教本の写真を撮るのは禁止だが、メモを取るのは良いという、なんだかよく分からない決まりがある。

やはり、百聞は一見に如かずというので、銃について知りたい場合は、実際に自分で予備自衛官補になって確かめるのが、一番だと思う。人に語ることはできないのだが。

ともかく結論としては、予備自補の訓練はためになる。是非とも参加してみるべきだと思う。私自身も、訓練が始まる前に、情報を収集しようとしたが、かなり断片的な情報しか得られなかった。ここでは、差し障りのない程度で、私が事前に知りたいと思っていた情報を書いてみようと思う。駐屯地ごと、区隊ごとにだいぶ違うと思われるが、基本は同じだ。

ここでは、営内の売店や、必要な持ち物について語ろうと思う。

何を持って行くべきか。これは、A課程初日では、誰もが失敗すると思う。用意すべきものとしてあらかじめ渡されるプリントの記述は、実に不親切だからだ。ここでは、私が必要だと感じた物品を挙げる。

現金

数万ぐらいあれば十分足りるだろう。文無しで行くのは無謀である。多少の現金は必要だ。理由は、必要不可欠ではないが、あれば嬉しい物品を営内の売店で買うのと、訓練でかなり汗をかくので、スポーツドリンクが欠かせないためだ。

ジャージ

長袖長ズボンのジャージが必要である。

Tシャツ

白色無地かOD色(Olive Drabの略、こういう色である。深緑とでもいうのだろうか)の無地のシャツであれば、まず問題はない。枚数は、何枚持っていっても無駄にはならない。日中に汗をかいて着替えたい時もあるので、多めに持っていくといいだろう。ただし、速乾性に優れたシャツを買うべきだ。もし何をかっていいか分からなければ、とりあえず安物を何枚か買って、残りは営内の売店で買うという手もある。速乾性に優れたシャツが、一枚800円程度で売っている。

靴下

分厚い靴下を持って行くべきである。というより、薄い普通の靴下を持って行く必要はない。スポーツ用と謳っている靴下は、大抵厚手になっているので、そういうものを買うといいだろう。これも、営内の売店で悪くない厚手の靴下が売っている。値段は、一足当たり300円程度だ。なぜ分厚い靴下が必要かというと、半長靴を履くためだ。半長靴というと聞き慣れない人もいるだろうが、これは別に自衛隊用語というわけでもない。読んで字の如く、「半ば長い靴」である。すねの半分ぐらいを覆うブーツとでもいえば分かりやすいだろうか。もちろん、革靴であり、かなり硬い。

タオル

所謂バスタオルを持って行く必要はない。巨大なバスタオルを持って行くぐらいなら、普通サイズのタオルをたくさん持って行くべきである。カバンの容積は限られているので、風呂上がりに全身を拭くという、一つの用途にしか使えないバスタオルは、容積の無駄である。もし一枚のタオルでは、風呂上がりの体を拭くのに十分ではないと思うのならば、二枚、三枚と使えばいいだけの話だ。バスタオル一枚分のスペースで、通常のタオルが何枚も持って行ける。枚数については、これも、多めに持っていくべきだ。タオルについても、売店で、一枚300円程度の値段で売っている。また、ハンカチも、通常のタオルで代用できる。訓練中に着る作業服のポケットは大きいので、タオルをハンカチ代わりに持っていくことができる。

ボディソープ等

風呂には、ボディソープやシャンプーの類は、備え付けられてはいない。従って、これらは愛用品を自分で持っていくか、あるいは売店で買う必要がある。ここでひとつ、注意を要することがある。持ち込むボディソープとして、固形石けんは適さないということである。いちいち風呂から部屋まで持って帰って保管するのが面倒だからだ。ポンプ式の容器に入った、液状のボディソープを使うべきである。また、洗濯をしなければならないので、洗剤が必要である。これも、売店で売っている。

メモ帳

手のひらに収まるサイズのメモ帳が必要である。メモ帳とペンは、体育訓練や風呂を除いて、常に携行すべきである。作業服のポケットは十分大きいので、メモ帳とペンを持ち運ぶのに不自由はない。なぜメモ帳が必要なのか。それは、覚える事柄がたくさんあるからだ。どういう順番でどういう動作をすればいいのか、何時何分にどこに何を持って集合すればいいのか。すべてを覚えるのは不可能である。メモを取るべきだ。

その他

ガムテープやカラーテープがあると、何かと重宝する。これは売店で売っている。

首にかけるチェーンが必要である。これは、別におしゃれのためではない。自分に割り当てられたロッカーは、部屋を出る時は必ず鍵をかけて、鍵自体は常に肌身離さず持っていなければならないとされている。そこで、皆、首から鍵を提げることになる。風呂に入る時でさえも、鍵は首にかけて持っていく。ところが、あらかじめ鍵に付いているヒモは、非常に頼りない。それに、衛生的にも問題がある。そこで、首にかけるチェーンを一本買うべきである。これは、売店で100円で売っている。

訓練中は、常にハンカチとティッシュを携行するように言われる。作業服のポケットは大きいので、ハンカチの代わりにタオルでもいい。ポケットティッシュは、売店でも売っている。

洗濯物を干すために、ハンガーと洗濯バサミが必要である。これは、売店でも安価で売っているが、おそらく外では、もっと安価で買えるところもあるだろう。

売店について

営内の売店では、かなり便利な物が売っている。例えば衣服だ。やはり自衛官の需要という物が分かっているらしい。シャツに関しては先ほども述べたように、速乾性のシャツが売られているし、走りやすそうな短パンや、一足一万円以上する運動靴なども売られている。主にGショックなどの頑丈な腕時計もある。アーミーナイフもある。変わった所では、携帯コンロなども売っていた。ノートやペンなどの文房具も売られている。歯ブラシやひげそりや洗剤などの日用品もある。実際、予備自補の訓練中に、「ああ、アレを持ってくれば便利だったろうな」と思ったソレは、大抵、売られていたりする。

変わりどころとしては、帽子の形を整える為の針金というものがある。これは一本50円と安いので、買っておくといいだろう。これは必須ではなく、また訓練とはあまり関係がないが、やはり見た目にカッコいい。実際、教官達は皆、帽子にこの針金を仕込んでいる。

食料品

食料品も売られている。もっとも、自衛隊のメシは、十分すぎるほどの量があるので、普通に食べていれば、腹が減るということはない。ただ、甘い物が食べたくなることはあるだろう。そういう時には利用するといいだろう。

自分のロッカーには、スポーツドリンクを常備しておくべきである。炎天下の中では、ただ立っているだけで多量の汗をかく。居室にての休憩中に、スポーツドリンクを一口飲めるかどうかの差は大きい。