2007-03-28

ネオジム磁石のブレスレット

先日紹介した、ネオジム磁石のブレスレットが、やっと届いた。さっそく装備する。

そういえば、昔は防具屋の近くに意味ありげなオヤジがいて、「ぼうぐは そうびしないと いみが ないぞ」などと教えてくれたものだ。近頃、こういう親切な人が耐えて久しい。

さて、今日はクエストがある。トム爺さんを押すのではなく、三流ホテルの皿洗いのクエストだ。さっそくいくと、パーティメンバーの、職業おばはんの人から、次のように言われた。

おばはん曰く、「へぇ~それ強い磁石なんだ。もぅ~すごい波動が出てるんじゃない」
我、答えて曰く、「科学の名において、有神論者に災いあれ」

まあ、つづめて言うと、ネオジム磁石の面白いブレスレットを身に付けてバイトに行くと、磁石が健康にいいと信じているおばはんが、波動がでていると宣ったわけだ。

一体波動とはなんだろうか。確かに間違いではない。電磁波(もちろん可視光も含む)を、一般に波動というのだろうが、このおばはんの口にする波動という言葉は、どこかオカルトじみていた。このおばはんは、本当にこの手の似非科学がすきなのだ。サプリメント愛用者であり、バイト中の水分補給に酸素水を愛飲している。サプリメントなんて、緊急に何かを摂取しないといけないときぐらいしか使う必要がないし、酸素水は愚の骨頂、そもそも酸素は水にほとんど溶けないのだ。ペットボトル一本飲み干しても、一呼吸分の酸素に相当するかどうかも怪しいものだ。第一、水に溶けた酸素をどうやって吸収するというのか? 我々は、何十平方メートルもある肺胞で酸素を取り入れるのだ。この面積はどうしても必要なのだ。皮膚呼吸などというものが、いかに馬鹿げているか分かるだろう。

本当に、「水商売」は昔からなくならない。

そして、磁石の健康への影響も、統計的には、存在しないと結論できる。しかし、何故人はこの手の似非科学に惹かれるのだろうか。

2007-03-27

what's wrong with Trackback

トラックバックという機能を知ったときは、面白いとは思ったが、さほど興味を抱かなかった。なにしろ私には、「どうぞ私にスパムを送りつけてください」と宣言しているように感じられたからだ。

こちらへリンクを自動的に貼ってもらうという仕組みは、当然スパムに利用されるに決まっている。案の定、もはやトラックバックはスパムだらけである。このスパムに対して、各社とも知恵を絞っている。単純な単語やIPなどのフィルタから、トラックバック元に、こちらへのリンクがなければ無効にするという機能、あるいは、同一のリモートホストから、自社のブログサービスへ、一度に大量のトラックバックが送られた場合、スパムとみなすなどである。これらの努力はすばらしいが、しかし、そこまでしてトラックバックを使いたいものかと疑問になる。

ところで、bloggerには、バックリンクという仕組みがある。これは、自分へリンクしている所へ、こちらからリンクをはる機能だ。そもそもトラックバックは、Movable Typeが始めたもので、ある記事にたいするリンクである。自分の記事にリンクしているサイトは、明らかに関連のある事柄を扱っているに違いない。では、こちらからもリンクしてやろうというわけだ。この仕組みは、なかなか面白い。このバックリンクへスパムを使用とするならば、Googleにクロールされる形で、スパム先へのリンクを提供し続けなければならないからだ。

とはいっても、バックリンクを提供できるのは、大手検索サイトぐらいなものだろう。特にGoogleだ。

2007-03-25

リアル砂の女(主人公は女)

http://www.h-keizai.com/article-2007-02/p078-kokuhaku.html 各種募集など http://ninaite.or.jp/osirase/061003_nikkapu.htm http://www.obira.on.arena.ne.jp/nougyou-iinkai/n-taiken/nougyou-taiken.html http://www.koukeisya-niikappu.jp/YOURYOU.htm http://www.ja-enyu.com/sub/sub05/sub05_2.htm http://www.ja-shinshinotsu.jp/taikensha/taikensha_2.htm http://ninaite.or.jp/osirase/060815_syari.htm http://www.ja-shari.or.jp/taisaku/INFO/info.htm  条件として目立つのが、「独身女性」だ。また、男女募集となっていても、選考段階で、「残念ながら」、男がはじかれるようになっている。まさか、阿部公房の砂の女が、この時代においても、リアルに存在するとは思わなかった。真実は小説より奇なりや?

2007-03-24

いい加減にしろ、黄昏フロンティア

http://www.tasofro.net/cgi-bin/cbbsD/cbbs.cgi?mode=al2&namber=1993&rev=0&no=0  >正式に対応を保障しているOSはWindowsXPと2000のみになります。  嘘をつけ嘘を。  対応しているのではなく、たまたま動いているように見えるだけだ。特に、最初は、デバッガでアタッチして起動させただけで例外を投げるという、すばらしいコードだったではないか。いまでも、Vistaの互換性検証ツールで起動させることすらできない。

2007-03-22

I don't like Automatic Transmission.

 AT車をはじめて動かしてみたが、どうも好きになれない。車の免許を取る前は、「もはやAT車全盛の世の中なのだから、MTなど一部の物好きに供されるものだ」と考えていたのだが、どういう風の吹き回しだろう。  アクセルを踏まなくても動き出すのがまず気に食わない。アクセルペダルを緩めても、あまり減速しないのも気に食わない。そういえば、MT車でブレーキペダルは、停止するときぐらいしか踏んでいなかった。  最も気に食わないのは、勝手にギア比が変わることだ。走っていると、ギア比が勝手に変わったことが察せられ、実に気色悪い。  まあ、親父も車やバイクが好きで、そのために転職までしたほどだから、ある意味、親父譲りってところなのだろうか。

2007-03-18

Does VC8 optimize quick sort?

バイナリサーチは末尾再帰で書けるので、最適化できる。では、末尾再帰ではない再帰は、どのようなコードが生成されるのか。たとえば、クイックソートだ。

template < typename Iterator >
void quick_sort(Iterator first, Iterator last)
{
    if ( std::distance(first, last) < 3 )
    { return ; } // 末尾

    Iterator left(first), right(last) ;
    ++left ;
    --right ;

    while ( left < right ) 
    {
        while ( left <= right && *left <= *first )
        { ++left ; }
        while ( left <= right && *right > *first )
        { --right ; }

        if (left < right )
        { std::iter_swap(left, right) ; }
    }

    std::iter_swap(first, right) ;

    quick_sort(first, right) ;
    quick_sort(++right, last) ; //末尾
}

どうもスマートに書くのは難しいが、とりあえず実験の用には足りるだろう。これはどう見ても末尾再帰ではない。これをVC8でコンパイルしてみると、二つ目の再帰呼び出しは、最適化されてループになっていた。なるほど、そういうこともできるのか。

2007-03-16

Does VC8 optimize Tail Recursion?

 末尾再帰というものがある。ある関数が、最後に自分自身を呼び出すように書かれている場合、もし分岐があるならば、それぞれの分岐の最後に、自分自身を呼び出すように書かれている場合、それをTail Recursion(末尾再帰)という。下に例を示す。
void print_hello(int const n) { if ( n == 0 ) { return ; } else { std::cout << "hello" << std::endl ; return print_hello(n - 1) ; } } double power( double const x, int const n ) { if ( n == 0 ) { return 1.0 ; } else { return x * power(x, n - 1) ; } }
 print_hello関数は、引数に与えられた数だけ、helloと出力する関数である。power関数は、xのn乗を計算する関数である。しかし、このように再帰的に記述するのは、C++らしくない。我々C++プログラマは、副作用がたっぷり詰まった、forやwhile文のループを好むものだ。なぜならば、たとえばMS-Windows X86の場合、関数を呼ぶというのは、それだけでスタックを消費するのだ。今の時代にC++を書く、根性のあるプログラマは、皆CPUのサイクル数や、数バイトのメモリ消費を気にするパフォーマンスの信奉者である。再帰のオーバーヘッドなど許されるはずがない。  しかし、ちょっと待って欲しい。次のような単純な変換を施すだけで、この糞みたいなオーバーヘッドを持つ関数は、単なるループに変わる。
void print_hello(int n) { LOOP : if ( n == 0 ) { return ; } else { std::cout << "hello" << std::endl ; --n ; goto LOOP ; } } double power( double x, int n ) { double tmp(x) ; LOOP : if ( n == 0 ) { return tmp ; } else { tmp *= x ; --n ; goto LOOP ; } }
 すばらしい。実に単純な変形だ。コンパイラにできないはずがない。  実際、主要なコンパイラは、末尾再帰を最適化できる。この末尾再帰という考え方は、副作用を忌み嫌う関数型言語の信者にとって、崇拝の対象である。特にLISP教徒は、再帰がなければまともにループを書くことができない。LISPの方言のひとつ、Schemeなどは、 「Thou shalt not waste stack by tail recursion. if thou defy god's will, thy are evil beast, slow belly, and pagan.」 「処理系は末尾再帰にてスタックの消費をしてはならぬ。もし我が意に沿わざれば、汝は悪しき獣、懶惰の腹、異教徒なり」  とまで、規格書の中で明言している。まあ、私にとって、Schemeが異教徒なのだが。  さて、関数型言語は異教徒ではあるかというと、最近のC++の動向を見るにつけ、そうもいえなくなっている。しかし、どの程度できるのだろうか。さっそく確かめてみよう。  確かめるからには、何か実用的なコードにしなければならない。バイナリサーチなどどうだろう。あれは、スタックを消費せずに、ループでも実装できる。あれを再帰で書いて、コンパイラが最適化できるか確かめてみよう。  まず、典型的なC++教徒の書くバイナリサーチを書いてみる。
template < typename Iterator, typename T > bool binary_search( Iterator first, Iterator last, T const & value ) { typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last) ; Iterator mid ; for ( ; n != 0 ; n = n / 2 ) { mid = first ; std::advance(mid, n / 2) ; if ( *mid < value ) { first = ++mid ; } else { last = ++mid ;} } return bool( *first == value ) ; }
 これはどうみても、典型的なC++のバイナリサーチだ。さて、早速再帰で書いてみよう。特に難しくはない。
namespace detail { template < typename Iterator, typename T > bool binary_search(Iterator first, Iterator last, T const & value , typename std::iterator_traits<Iterator>::difference_type const n) { if ( n == 0 ) { return bool( *first == value ) ; } Iterator mid(first) ; std::advance(mid, n / 2 ) ; if ( *mid < value ) { return binary_search(++mid, last, value, n / 2) ; } else { return binary_search(first, ++mid, value, n / 2) ; } } } // namespace detail template < typename Iterator, typename T > bool binary_search( Iterator first, Iterator last, T const & value ) { return detail::binary_search(first, last, value, std::distance(first, last) ) ; }
 私はまだ、C++への信心と修行が足りないし、ましてや異教徒の操る再帰は得意ではないが、こんなものだろう。さっそくこれを、VC8 SP1でコンパイルしてみる。VC8の最適化のほどを見せてもらおう。五千円だして買っただけの価値はあるのだろうか(学生というのはいい身分だ)  まず、これがC++版のbinary_searchだ。これを次のように呼ぶと。
binary_search<int *, int>(&v[0], &v[1000], 12700) ;
00401120 |> 99 /CDQ 00401121 |. 2BC2 |SUB EAX,EDX 00401123 |. D1F8 |SAR EAX,1 00401125 |. 813C81 9C310000 |CMP DWORD PTR DS:[ECX+EAX*4],319C 0040112C |. 7D 04 |JGE SHORT test.00401132 0040112E |. 8D4C81 04 |LEA ECX,DWORD PTR DS:[ECX+EAX*4+4] 00401132 |> 85C0 |TEST EAX,EAX 00401134 |.^75 EA \JNZ SHORT 00401120
 前後を省略するが、これがループである。binary_search関数は、呼び出したところでインライン展開された。ループ版のbinary_searchはこのようになる。再帰版のbinary_searchも、このようになることが理想だ。さて、どうなるだろう。早速比較しよう。
00401370 /$ 85C0 TEST EAX,EAX 00401372 |. 74 16 JE SHORT 0040138A 00401374 |. 56 PUSH ESI 00401375 |. 8B37 MOV ESI,DWORD PTR DS:[EDI] 00401377 |> 99 /CDQ 00401378 |. 2BC2 |SUB EAX,EDX 0040137A |. D1F8 |SAR EAX,1 0040137C |. 393481 |CMP DWORD PTR DS:[ECX+EAX*4],ESI 0040137F |. 7D 04 |JGE SHORT 00401385 00401381 |. 8D4C81 04 |LEA ECX,DWORD PTR DS:[ECX+EAX*4+4] 00401385 |> 85C0 |TEST EAX,EAX 00401387 |.^75 EE \JNZ SHORT 00401377 00401389 |. 5E POP ESI 0040138A |> 8B01 MOV EAX,DWORD PTR DS:[ECX] 0040138C |. 3B07 CMP EAX,DWORD PTR DS:[EDI] 0040138E |. 0F94C0 SETE AL 00401391 \. C3 RETN
 これが、再帰版のbinary_search関数である。呼び出したところにインライン展開はされなかったものの、再帰ではなくなっている。思うに、binary_search関数自体はインライン展開されているのだろう。detail::binary_search関数は、末尾再帰が最適化されて、ループに直されるものの、そのトップレベルの関数自体がインライン展開されることはないのだろう。これには何か、理由があると思われる。  さて、肝心のインストラクションコードはどうだろうか。00401377番地から始まるループを見て欲しい。すばらしい出来だ。関数自体がインライン展開されないので、0x319C(12700)は即値ではなくなっているものの、なんとレジスタである。そのほかはすべて、ループ版と同じだ。再起によるオーバーヘッドはなくなった。単なるループとまったく同じである。もちろん関数呼び出しにかかるコストはあるが、それは一回だけで、無料同然に安い。5千円の価値はあるといえよう。    しかし、ここまで分かりやすい結果になるとは思わなかった。  因云、VC8のイテレータは、デフォルトで範囲外チェックを行う。コンピュータがネットワークにつながることが当たり前になった今の時代、パフォーマンスよりもセキュリティの方が重要だと叫ばれている。セキュリティの確保にかかるコストは無料ではない。ヘビーなパイプラインを持つCPUにとって、条件分岐は禁忌だ。さて、VC8の、セキュアなイテレータは、どの程度パフォーマンスに影響を及ぼすのか。  先ほどの関数に、セキュアなイテレータを通してみると、恐ろしく長いコードが生成された。範囲外をチェックするコードは、恐ろしく頻出するので、インライン展開しないほうが良いと判断されたのか、関数になっている。山のようなpushとpopがある。汎用レジスタが、全然足りていないのだ。うーむ、セキュリティは無料ではないとはいえ、これはすこし、セキュアなイテレータの使用をためらってしまう。  恐らくは、大半の場合は、セキュアなイテレータを使うべきなのだ。それは分かっている。当然だ。しかし、この生成されるコードは……、いや、これは私が古いからなのだ。まったく。この業界は、どうかしている。経験に裏打ちされた熟練の技というものは存在しない。10年前、いや5年前の常識だって通用しないのだ。むしろ、そういう古い知識は、新しい技術習得の邪魔になる。やんぬるかな

2007-03-15

Why Japanese translation of south park is gay

 最近、South Parkというアニメに、クレイジーになっている。しかし、日本語吹き替えはゲイだ。何故だろう。  まず考えられる説として、声優の演技がケツの穴なのかもしれない。特に、OPの歌はひどい。しかしどうも、私はここに、英語と日本語の違いによるものがあるのではないかと思っている。日本語にはない独特の――うまく表現しがたいが――、リズムのようなものがあると考えている。たとえば、Full Metal Jacketの、冒頭から最初の六分ほどの、先任軍曹の語りだ。  英語が分からなかったとしても、この日本語にはないリズムは感じられるのではないだろうか。ただ、FMJの罵倒は、少々古臭いのだが。  もうひとつ思うことは、罵倒の文句だ。日本語には、文になっている罵倒が少ないのではないだろうか。バカ、アホ、マヌケなどが罵倒に際して、よく用いられるが、suck my bollocks とか、lick my ass あるいは、fuck yourself などといった罵倒が、日本語で使われることは無いように思われる。唯一思いつけた定型文での罵倒は、「お前の母ちゃんデベソ」だが、これはあまりにも幼稚すぎる。そもそも、今使われているのだろうか。他に何かあるだろうか。「チョーシ、コイてんじゃねーぞ」等だろうか。しかし、どうも迫力に欠ける。  あるいは、文化的なものなのだろうか。日本語訳には、英語にあるような毒が抜けている感がする。微妙なニュアンスが、訳せないのだろうか。この投稿にあたって、適当な既存のラベルがなかったので、新たなラベル:IMAOを使うことにした。これはそもそも、IMHO(In My Humble Opinion : 私の愚見では)という略語に対する、ネット上のスラングで、In My Arrogant Opinion(吾輩の思し召しは)である。これだけ長々と説明しないと、IMAOのもつニュアンスですら伝わらないのだから、無理もないのだろうか。   注釈: ゲイ(gay):くだらない、つまらない ケツの穴(asshole):ドアホ  私はgayという単語を注釈の意味で解釈している。実際、このように使われているからだ。しかし、いい加減に書くことはできないので、調べようとしたが、私の持っているジーニアス英和辞典やロングマン等には、こういう意味は載っていない。ホモとか、快活な、などと言う意味でのっている。Urban Dictionaryが、この手のスラングの用法についてくわしいようだ。often used to describe something stupid or unfortunateとある。私の解釈は間違っていなかったようだ。

2007-03-13

how to write Merge sort?

http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/index.htm  マージソートを実装した。
namespace hito { namespace detail { template < typename Iterator > void merge_sort( Iterator first, Iterator last , typename std::iterator_traits<Iterator>::difference_type const n , typename std::iterator_traits<Iterator>::value_type * buf ) { if (n < 4) { for ( ; first != last ; ++first) { Iterator iter = std::min_element(first, last) ; if (iter != first) std::iter_swap(first, iter) ; } return ; } Iterator mid(first) ; std::advance(mid, n / 2) ; merge_sort(first, mid, n / 2, buf) ; merge_sort(mid, last, n / 2, buf) ; std::copy(first, mid, buf) ; typename std::iterator_traits<Iterator>::value_type * const end(buf + n / 2) ; while ( buf != end && mid != last ) { if ( *buf < *mid ) { *first = *buf ; ++buf ; } else { *first = *mid ; ++mid ; } ++first ; } std::copy(buf, end, first) ; } } // namespace detail template < typename Iterator > void merge_sort( Iterator first, Iterator last ) { typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last) ; if ( n == 1 ) return ; // Done typedef typename std::iterator_traits<Iterator>::value_type type ; type * buf = new type[(n + 1) / 2] ; detail::merge_sort(first, last, n, buf) ; delete[] buf ; } } // namespace hito
 結局、どう実装するのが一番最適なのだろう。これはBidirectinalIteratorでもソート可能だ。しかし、RandomAccessIteratorの場合は、引数のnなどいらない。ランダムアクセスイテレータに対して、std::distanceはフリーだからだ。実際どうするべきなんだろう。  そしてふと、Nicolai JosuttisのSTL本を紐解くと、驚くべき事実が載っていた。stable_sortのイテレータはRandomAccessIteratorである。そんな馬鹿な。VC8のDinkumwareはBidirectionalIteratorでもソート可能だ。これは一体どういうことだ。規格を読むと、25.3.1.2に、確かにRandomAccessIteratorとある。しかし、実際にBidirectionalなlistのイテレータを渡しても、ソートできる(listはもっといいメンバ関数があるのだが) ヘルプや、Dinkumwareのソースでは、双方向イテレータになっている。ふーむ。VCの独自仕様なのだろう。実際、マージソートは、双方向イテレータでも、それほど問題はないと思われる。

insertion sort

 http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/CourseHome/index.htm  insertion sortを、C++的に実装した。
namespace hito { template < typename BidirectionalIterator > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last ) { BidirectionalIterator pos = first ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; BidirectionalIterator iter = pos, sorted_iter = pos ; for (--iter ; iter != first && key < *iter ; --iter, --sorted_iter) { *sorted_iter = *iter ; } if ( key < *iter ) // check first element { *sorted_iter = *iter ; --sorted_iter ; } *sorted_iter = key ; } } template < typename BidirectionalIterator, typename BinaryPredicate > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last, BinaryPredicate op ) { BidirectionalIterator pos = first ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; BidirectionalIterator iter = pos, sorted_iter = pos ; for (--iter ; iter != first && op(key, *iter) ; --iter, --sorted_iter) { *sorted_iter = *iter ; } if ( op(key, *iter) ) // check first element { *sorted_iter = *iter ; --sorted_iter ; } *sorted_iter = key ; } } } // namespace hito
 しかし、これはちょっと汚い。reverse_iteratorを使ってみると、こうなる。
namespace hito { template < typename BidirectionalIterator > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last ) { BidirectionalIterator pos = first ; std::reverse_iterator<BidirectionalIterator> const rend(first) ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; std::reverse_iterator<BidirectionalIterator> riter(pos), rsorted_iter(pos) ; for ( --rsorted_iter ; riter != rend && key < *riter ; ++riter, ++rsorted_iter) { *rsorted_iter = *riter ; } *rsorted_iter = key ; } } template < typename BidirectionalIterator, typename BinaryPredicate > void insertion_sort( BidirectionalIterator first, BidirectionalIterator last, BinaryPredicate op ) { BidirectionalIterator pos = first ; std::reverse_iterator<BidirectionalIterator> const rend(first) ; for ( ++pos ; pos != last ; ++pos ) { typename std::iterator_traits<BidirectionalIterator>::value_type key(*pos) ; std::reverse_iterator<BidirectionalIterator> riter(pos), rsorted_iter(pos) ; for ( --rsorted_iter ; riter != rend && op(key, *riter) ; ++riter, ++rsorted_iter) { *rsorted_iter = *riter ; } *rsorted_iter = key ; } } } // namespace hito

the best learning site ever and never

MIT's OpenCourseWare  これはすばらしい。MITの講義を、無料で、いつでも見ることができるのだ。しかも、今年中に、すべての講義を見れるようにする予定らしい。何しろ、MITは年間の授業料が4万ドルぐらいするのだ。ありがたやありがたや。しかし、動画は明らかに、教授の動きに合わせて、ズームインアウトなどをしていたりするところからしても、明らかに人の手で撮影されている。馬鹿にならない人件費がかかっていそうだ。  まず手始めに、アルゴリズム入門の講義のストリーミング動画を見てみた。しかし、これが入門だとは信じられない。恐ろしく密度の高い講義だ。しかも分かりやすい。

2007-03-11

glad im japanese

A Little Taste of Editing Holy Gay! タバコがかっこ悪いことは言うまでもないが、なにもロリポップはなかろうて。 そもそも、スーパーマーケットで実弾が売っている世界で、創作のアニメに描かれている銃を規制したところで、何になるというのか。メリケンは実に、理解しがたい人種だ。

2007-03-09

Some funny videos

Make Love, Not Warcraft これは、World of Warcraftをパロディにした、サウスパークのアニメである。Wikipediaにも、詳しい解説が載っている。YouTubeやGoogle Videoも軒並み削除されているので、これもいつまでもつことやら。 これは、ローワン・アトキンソンが演じる、デートガイドハウツーである。必見だ。

Great YouTube video : CAUTION! You probably lose your money.

私は、首飾りや指輪、腕輪などといった装身具に興味を持たない人間である。私はよくいる、外見に一切気を使わない人間の一人であり、服にも一切こだわっていない。にもかかわらず、このすばらしいYouTubeの動画は、この私にブレスレットを売りつけてしまった。これを一回見ただけで、もうどうしようもなくこのブレスレットが欲しくなってしまったのだ。この動画は危険である。あなたから50ドルを奪ってしまう。

この商品は、Bandoleer Braceletだ。購入も、ここから行える。価格40ドルで、海外への送料が10ドルだ。ちなみに、この商品を注文すると、つぎのようなメールが送られてきた。

Your order at Dynomighty has been received. Due to significant response from our YouTube video, we currently have delays in order fulfillment. We are making every effort to ensure your order is shipped ASAP. Estimated delivery is currently 10 days.

Dynomightyへの注文を受け付けました。ただいま、YouTube動画への反響がとても大きいために、商品の発送が遅れております。なるべくはやく商品をお届けするよう、努めています。発想までには10日ほどかかると思われます。

これは大変そうだ。

What THE FUCKING great japan is!

 鹿児島とかいう、日本の隅のほうにあるどうでもいい所の議員に立候補した人民とその関係者等12人が、袖の下を通した疑いで逮捕された。このたび、どうやら司法は無実であるという判断をしたようだ。  正直言って、この老いぼれ12人が無実かどうかなど、社会全体には、どうでもいいのだ。この12人が無罪放免されようと、獄中で野垂れ死のうと、我々の生活にはまったく関係のない話だ。もっとも重要視すべきは、警察、即ち公権力への信頼である。信頼はつまるところ、事件解決をもって得られるのだ。神聖にして畏れるべき大日本に必要なのは全体社会の利益だ。個人など知ったことではない。  だからこそ、警察は取り調べの際の録音録画をしないのだ。一般大衆が見たとしても、革命の危機にこそなれ、公共社会の利益となりはしない。「ウン、ハイ以外声を出すな。一切否定するな!口で糞たれる前と後にサーと言え。」同胞よ、我々は、近年の取り調べの録音録画要求について、断固として跳ね除けねばならない。日本を革命の危機から阻止するためである。人民に栄えあれ。

Expression Template

C++ Templatesに載っているExpression Templateの実装は、嫌いだった。物凄く面倒なのだ。これを実装するぐらいだったら、自前でループを書いたほうが、まだましだろう。

ところで、C++ Template Metaprogrammingを読んでいると、より分かりやすい方法が見つかった。C++ Templatesに載っている方法は、各種演算のための参照でラップするクラスと、演算子をオーバーロードするテンプレート関数があったのだが、C++ Template Metaprogrammingのサンプルでは、この演算方法を、テンプレートパラメータとしていた。

struct plus
{
  static float apply(float a, float b)
  { return a + b ; }
} ;

struct minus
{
  static float apply(float a, float b)
  { return a - b ; }
} ;

template < typename L, typename OpTag, typename R >
struct Expression
{
  Expression(L const & l, R const & l)
    : l(l), r(r) { }
  float operator[](unsigned index) const
  { return OpTag::apply(l[index], r[index]) ; }

  L const & l ;
  R const & r ;

} ;

template < typename L, typename R >
Expression<L, plus, R> operator + (L const & l, R const & r)
{
  return Expression<L. plus, R>(l, r) ;
}

なんて分かりやすいんだろう。C++ Templatesの実装では、Expression_Addとか、Expression_Subなどをそれぞれ用意しなければならないが、こうすると、かなり分かりやすくなる。なぜ今まで思いつかなかったのだろう。分かってしまうと単純なのに、自力で発見することはできない。コロンブスの卵というやつだろうか。

2007-03-07

Concepts Extending C++ Templates For Generic Programming

この情報は恐ろしく昔のもので、現在のドラフト規格とまったくあっておりません。検索で飛んでこられた方は、この情報を信用せず、ご自分で規格をご確認ください。

 これは最高にためになる動画だ。
 コンセプトとは、C++のパラダイムのひとつ、ジェネリックプログラミングを、もっと分かりやすくするための文法だ。

 前半の5分ほどは、ジェネリックプログラミングはなんであるかを解説している。

The reason we think that we can make it simpler is that many of the way people use template now are... tricks! There're complelcated tricks. You can't even read in the book in many faces. You have to dig for newsgroup to see how they work recall look at boost C++ library to see what those guys did.

 今のテンプレートは、複雑なトリックを多用しすぎている。多くのトリックは、本にも載っていない。Boost C++ライブラリを書いている連中が何をやっているのかを知るためには、ニュースグループを調べなければならない。(原文が正しい自信がない)

 conceptには三つの機能がある。
Concept Difinitions
 ある型にたいする要求を定義する。たとえば、ある型TはT:func()というメンバ関数を持っていなければならないとか、T::value_typeという型が定義されていなければならないなどだ。
Where Clauses
 テンプレートパラメータに必要なコンセプトを明示的に指定できる。
Concept Map
 既存の型を、どのようにコンセプトの要求どおりに使うかを指定できる。個人的な感想は、恐ろしく賢いマクロか、恐ろしく便利なシンタックスシュガー。

template < typename T > where LessThanComparable<T> const T & min(const T & x, const T & y) {return x < y ? x : y ;}

 この例では、型Tは、less than演算子を持っていなければならないというコンセプトが示されている。たとえば、比較演算子としてgreater than演算子(>)を使った場合は、コンパイラがエラーを出す。less than演算子で比較できない型を渡した場合も、コンパイラはエラーをだす。しかも、コンパイラが吐くエラーは、「LessThanComparableの要求を満たしていません」等といった、人間に分かりやすいエラーだ。従来の、インスタンシエイトの過程を追っていくような、人間にとって暗号に近いエラーメッセージではない。

それでは、LessThanComparableというconceptはどうやって定義するのか。

concept LessThanComparable< typename T > { // Syntactic requirement bool operator < (T, T) ; // Semantic requirement axiom Irreflexivity(T x) { !(x < x) ; } axiom Asymmetry(T x, T y) { if (x < y) !(y < x) ; } axiom Transitivity(T x, T y, T z) { if (x < y && y < z) x < x ; } } ;

 文法的な要求と、意味的な要求を定義できる。講演では、axiomについては詳しく述べていない。しかし、この機能はどうやって実現するのか疑問だ。本当に、これをコンパイル時にチェックできるのだろうか。ここでの、syntactic requirementは、T型の引数を二つ取り、bool型を返す、less than演算子がなければならないというものだ。もちろん、現在のテンプレートパラメータのように、複数指定できる。Why not?

concept Foo<typename T1, typename T2, typename T3>{ } ;

 他にも、value_typeという型を持っていなければならない要求や、それらの型に対するコンセプトをネストして指定できる機能など。

concept InputIterator < typename Iter > { typename value_type ; // Iter must has typename Iter::value_type typename difference_type ; // Iter must has typename Iter::difference_type where SignedIntegral<difference_type> // Iter::difference_type must meet requirements of SignedIntegral concept Iter & operator++(Iter &) ; // pre-increment Iter & operator++(Iter &, int) ; //post-increment bool operator==(Iter, Iter) ; //equality comparison bool operator!=(Iter, Iter) ; //inequality comparison value_type operator * (Iter) ; // dereference } ;

 where clauseは、次のように指定できる。

template < typename Iter, typename T> where InputIterator<Iter> && EqualityComparable<InputIterator<Iter>::value_type, T > Iter find(Iter first, Iter last, const & value) { while( first != last && !(*first == value) ) { ++first ; } return first ; } ;

 ここで質問がある。InputIterator<Iter>::value_typeには、typenameの指定はいらないのかというものだ。もちろんここは型を指定すると決まっているので、必要がない。コンパイラは適切に判断できる。  たとえば次のようにすれば、conceptをサポートしていないコンパイラに対する、下位互換性も保てるだろう。

template < typename Iter, typename T> #ifdef COMPILER_SUPPORT_CONCEPT where InputIterator<Iter> && EqualityComparable<InputIterator<Iter>::value_type, T > #endif Iter find(Iter first, Iter last, const & value) { while( first != last && !(*first == value) ) { ++first ; } return first ; } ;

 さて、28分あたりから、いよいよ、超強力なconcept_mapの解説に入る。先ほどのfindという関数は、イテレータに対しては問題なく対処できた。でも、int型の配列に対してはどうだろう。int型の配列の先頭要素へのポインタは、十分にイテレータとして通用する。しかし、組み込み型であるので、value_typeやdifference_type等を持っていない。そこで、Concept Mapを使い、どうやってコンセプトに合うようにするか、いわばマップを行う。  Concept Mapとは、How(如何にして)conceptの要求を満たすかを定義する。たとえば、int型のポインタに、value_typeとdifference_typeが必要というのであれば、定義してやるだけだ。

concept_map InputIterator< int * > { typedef int value_type ; typedef ptrdiff_t difference_type ; } ;

 とはいっても、組み込み型だけでも、かなりの数がある。いちいちひとつずつやっていくのは面倒だ。ここは、テンプレートを使うべきだ。Why not?

template < typename T > concept_map InputIterator< T * > { typedef T value_type ; typedef ptrdiff_t dirrefence_type ; } ;

 これで、すべてのポインタは、InputIteratorのコンセプトを満たすようになった。

 コンセプトは、階層構造にすることができる。Concept Refinementという。

concept BidirectinalIterator< typename Iter > : InputIterator<Iter> { Iter & operator -- (Iter &) ; Iter operator -- (Iter &, int) ; } ; concept RandomAccessIterator< typename Iter > : BidirectionalIterator<Iter> { Iter operator + (Iter, difference_type) ; // ... } ;
every random access iterator is a bidirectional iterator is a input iterator

 ランダムアクセスイテレータは、バイディレクショナルイテレータであり、インプットイテレータである。  このヒエラルキーは、Overload Resolutionに絡めることができるらしい。たとえば、イテレータを、指定された個数分進めるadvanceであるが、

template < InputIterator Iter > void advance( Iter & x, Iter::difference_type n ) { while(m > 0) { ++x ; --n ;} } //O(n) template < RandomAccessIterator > void advance( Iter & x, Iter::difference_type n ) { x = x + n ; } // O(n)

 この例では、where clauseがないが、これは簡便なショートカットシンタックスである。意味も分かりやすい。ワーオ!

 まず、最初のadvance関数は、非常にジェネリックで、どんなイテレータでも使うことが出来る。しかし、ランダムアクセスイテレータの場合、これは無駄が多すぎる。そこで、RandomeAccessIteratorのコンセプトを使ってやる。コンパイラは、ベストマッチを探してくれる。ご存知の通り、Bidirectional Iteratorは、Input Iterator 「である」ので、最初の関数にマッチする。それにしても、タダでさえOverload Resolutionはややこしいというのに、さらに複雑になるのだろうか。現状では、テンプレートは、インスタンシエイトされてから、Overload Resolutionにかけられる。これだけでもややこしいというのに……。

 さて、さらにConcept Mapの話は続く。こんどは、あるコンテナの全要素をイテレートするというものだ。いわばfor-each loopだが、これをどうするか。もちろん自分でやってもいいのだが、全要素をループさせるというのは、よくある操作なので、楽をしたい。他の言語はどのようにしているかというと。

 Pythonは、イテレータとコンテナのプロトコルを定義している(ある決まった形でなければならない)
 Perlは、ユーザ定義型を無視する(ハァ? 組み込み型以外は知ったこっちゃないね)
 C#は、IEnumerableインターフェースを使う(既存の俺様コンテナは知ったこっちゃないね)
 C++0xは、concept mapを使う。
 次のForコンセプトを満たす必要がある。

concept For< typename X > { typename iterator ; where InputIterator<iterator> ; iterator begin(X &) ; iterator end(X &) ; } ;

 つまり、次のコードが、

vector<int> v ; for (int i : v) cout << i << ' ' ;
 シンタックスシュガーにより、このように展開される。
for( For<vector<int> >::iterator first = For<vector<int>>::begin(v) , last = For<vector<int>>::end(v) ; first != last ; ++first ) { int i(*first) ; cout << i << ' ' ; }

 何の解説もないが、原文のbracket parentheseの間に空白がないのは、意識してやっているのだろうか。これをできるようにしようという提案がされているのだが。もうひとつ、こんな風にコンセプトを明示的に使うことも出来るのだろうか。解説がないが。

 たとえば、int型の配列に対しては、次のようにする。

template < typename T, size_t N> concept_map For<T[N]> { typedef T * iterator ; T * begin( T array[N] ) { return array ;} T * end( T array[N] ) { return &array[N} ; } } ; int some_primes[6] = {2, 3, 5, 6, 11, 13} ; for ( int prime : some_primes ) std::cout << prime << ' ' ;

 これを使えば、STLとは微妙に違う、俺様コンテナであっても、コンセプトに合わせるようにしてやれば、俺様コンテナ自身を変更することなく、for-each loopに書けることができる。これはいい。既存の、既に問題なく動いているコードや、共通のフレームワークなどを変更せずにすむからだ。  質問があるが、コンセプトはnamespaceの中に入る。これは当然だ。

 ところで、STLのmultisetには、equal_rangeというメンバ関数がある。これは、引数として指定した値の範囲のイテレータを、pairで返す。コンテナではないが、for-each loopに必要な情報は、すべてそろっている。ではどうやってForコンセプトに合わせるのか。

template < InputIterator Iter > concept?map For< pair<Iter, Iter> > { typedef Iter iterator ; Iter begin(pair<Iter, Iter> & p) { return p.first ; } Iter end(pair<Iter, Iter> & p) { return p.second ; } } std::multiset<int> elements ; for ( int i : elements.equal_range(17) ) std::cout << i << ' ' ;

 恐ろしや恐ろしや。
 しかし、ひとつひとつ、これを定義していくのは、面倒である。我々はすでに、Containerというコンセプトを定義した。これを使えばよい。

template < Container C > concept_map For<C> { typedef Container<C>::iterator iterator ; iterator begin(C & c) { return c.begin() ; } iterator end(C & c) {return c.end() ; } } ;

 これで、Containerコンセプトを満たす型は、すべてforループにかけられる。とてもとても汎用的だ。

 テンプレートがらみのエラーメッセージに辟易としない人はいないはずだ。コンパイラは、インスタンシエイトの過程を追っていくので、エラーメッセージは膨大になり、人間が簡単に読めるものではなくなってしまう。しかも、内部の実装の詳細の識別子などがでてくるので、まずわけが分からない。

int main() { std::list<int> l ; std::sort(l.begin(), l.end() ) ; }

 上記のコードの、VC8のエラーメッセージは次の通りである。

D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'std::list<_Ty>::_Iterator<_Secure_validation>' から減少できませんでした
with
[
_Ty=int,
_Secure_validation=true
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1856) : 'std::operator -' の宣言を確認してください。
.\test01.cpp(10) : コンパイルされたクラスの テンプレート のインスタンス化 'void std::sort<std::list<_Ty>::_Iterator<_Secure_validation>>(_RanIt,_RanIt)' の参照を確認してください
with
[
_Ty=int,
_Secure_validation=true,
_RanIt=std::list<int>::_Iterator<true>
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'std::list<_Ty>::_Iterator<_Secure_validation>' から減少できませんでした
with
[
_Ty=int,
_Secure_validation=true
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1856) : 'std::operator -' の宣言を確認してください。
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'std::list<_Ty>::_Iterator<_Secure_validation>' から減少できませんでした
with
[
_Ty=int,
_Secure_validation=true
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1856) : 'std::operator -' の宣言を確認してください。
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'std::list<_Ty>::_Iterator<_Secure_validation>' から減少できませんでした
with
[
_Ty=int,
_Secure_validation=true
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\xutility(1856) : 'std::operator -' の宣言を確認してください。
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2676: 二項演算子 '-' : 'std::list<_Ty>::_Iterator<_Secure_validation>' は、この演算子または定義済の演算子に適切な型への変換の定義を行いません。(新しい動作; ヘルプを参照)
with
[
_Ty=int,
_Secure_validation=true
]
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3112) : error C2780: 'void std::_Sort(_RanIt,_RanIt,_Diff,_Pr)' : 4 引数が必要です - 3 が設定されます。
D:\Program Files\Microsoft Visual Studio 8\VC\include\algorithm(3231) : 'std::_Sort' の宣言を確認してください。

 これをまともに読める人間は、まずいないだろう。次のようになれば、読みやすいのではないかと思う。
「std::list::iteratorは、RandomAccessIteratorコンセプトを満たしていません。適合するconcept mapも見つかりません。」
 他にも、インスタンシエイトされる前に、テンプレートのコードが、コンセプトにあったものかを、コンパイラがチェックすることができる。たとえば動画の例では、InputIteratorは、less than演算子を使うことが出来ない。
 最後の質問でも出ているのだが、これらの機能にはコストがかかる。Boostのライブラリをふんだんに使ったコードのコンパイルには、かなりの時間がかかるが、コンセプトもテンプレートと同じく、かなり多くの処理を行わなければならない。どうなることやら。
 しかし、仕様が確定するのが2009年で、ISOの認可がおりるのが、2010年、それから主要なコンパイルベンダーが実装するのに、数年はかかるだろうから、案外楽観視していいのかもしれない。ムーアの法則が続いていればの話だが。

FAITH OF THE FALLEN by Terry Goodkind

 テリー・グッドカインド著、魔教の黙示を読み終えた。このシリーズの、第六部に当たる。今回は、かなり良作だった。  なぜこれが良作なのか。思うに、今回の話は、あまりにも人間的だからだろう。第四部や第五部では、リチャードがあまりにも強い魔法を使いすぎていて、実感に欠けることがあったように思う。その点、第六部では、魔法が表に、あまり出てこない。もちろん魔法はたくさん登場するが、その魔法について色々と語られることがない。探偵は拳銃が如何に機能するかについて、延々と語ることがないように――。そういう意味で、テリー・グッドカインドらしい話に戻ったと思う。  今回は、凝り固まった思想を持つニッキの話だ。端的に言えば、極端な全体主義とでも言うべきだろうか。努力してパンを得るより、パンを持っている者が、自分に分け与えるべきという思想だ。もちろん、過去の歴史から散々経験したとおり、人はイデオロギーで勤労意欲が沸いたりなどしない。働きたいものが働けず、物品の流通すら制限され、明らかに衰退しているにもかかわらず、人は個人の利益以上の、社会の利益を考える世界だ。リチャードはその世界を、自らの行動を示すことで変え始める。  それにしても「気迫」(スピリット)の像を見てみたいものだ。  ローブを風になびかせ、頭を上げて、背中を弓なりに反らし、何であれ自分を拘束しようとするものには抵抗するというしるしに両脇でこぶしを固めて、外の世界を見ている。

2007-03-04

ビル・Gからの手紙

「ビル・Gからの手紙」は週間アスキーで連載されていたコラムである。某巨大企業のビル・Gと名乗る人物から送られてきた手紙を、コモエスタ坂本が翻訳するという形をとっている。たとえば、次のようなで出しだ。

第17便
毎日毎日ラッシュ・アワーの電車でもみくちゃにされ、通勤地獄に悩まされている日本人の皆さん。私はポルシェで快適に通勤する、ビル・Gである。

第21便

家から遠く離れた会社に通勤するために、ニワトリより早く目覚めなければならない日本人の皆さん。私はワシントン湖のほとりに集う小鳥たちのさえずりと、やわらかな朝日と、そして愛する妻リンダの優しい声で一日をスタートさせるビル・Gである。

第31便

たった6枚のタタミ・マットの上で日々を過ごしている、親愛なる日本人の皆さん。私は最近完成された豪邸に引っ越したばかりのメディア王、ビル・Gである。

このビル・Gにかかると、Unicodeも、いまだに絵文字でコミュニケートする第三世界の野蛮人への配慮ということになってしまうし、クリントン元大統領も、ビル・Gのクローン人間ということになる。

ISBN4-7561-1855-0と、ISBN4-7561-3151-4の二冊である。

2007-03-03

How C++0x Programmer looks like?

典型的なC++0xプログラマ達  はたから見ると、皆ふざけているように見えるが、半分ぐらいは真面目なのだろう。個人的には311の方法がよさそうだ。もちろん、310の方法が使えるならば、それに越したことはないのだが。308は、まあ、一分間に3万ワードぐらい入力できるならばありかもしれない。

2007-03-02

Mark Russinovich wrote about Vista Memory

Inside the Windows Vista Kernel: Part 1 Inside the Windows Vista Kernel: Part 2  前回、Mark Russinovichは、Vistaのプロセスと、I/O周りについて書いていた。今回は、メモリと、起動終了の改善、並びに、パワーマネジメントについてである。  Windows95の時代、メモリは4MBしかなかった(クールな奴等は8MB積んでいた) その時代には、その時代にあったメモリ管理の方法がある。Vistaではどうなるのか。昔と比べると、だいぶメモリの制約はゆるくなった。 ダイナミック カーネル アドレス スペース(Dynamic Kernel Address Space)  32bitのVistaは、当然32bitなアドレスを使う。とはいっても、上位2GBは、カーネルが使うので、アプリケーションは、下位2GBしかつかえない。2kでも、BOOT.INIを変更し、さらにアプリケーション側でも/LARGEADDRESSAWAREを指定すれば、3GBまで使えないことはない。Vistaは、OSが使う領域を動的に変更するようだ。これによって、わざわざ起動時に、メモリをどのように使うか指定しなくてもよくなったそうだ。もっとも、これは32BitOSの話であって、64BitOSでは、仮想メモリはふんだんにあるので、こんなことは考えなくて良い。 メモリ プライオリティ(Memory Priorities)  どうやら、メモリにも優先度を付けたようだ。ページ単位のメモリに対して、8段階の優先度があるようだ。 スーパー フェッチ(Super Fetch)  あるアプリケーションを使っていて、すこしコンピュータから離れる。このとき、ユーザの入力がないことを検知したバックグラウンドのプロセス(アンチウイルスやデフラグなど)は、メモリをふんだんに使う処理を始める。その後、ユーザが戻ってきて、アプリケーションを再び使おうとすると、やけに反応が鈍いことに気づく。なぜならば、そのアプリケーションのメモリは、大量のメモリを使うバックグラウンドのプロセスのため、スワップファイルに退避させられたからだ。ディスクから再び読み込まなければならないので、使い始めが遅く感じる。こういうことを防ぐため、OSはアプリケーションの挙動を見張り、ファイルアクセスなどを記録しておく。そして、優先度の低いプロセスで、あらかじめファイルを読み込んでおく。こうすると、ユーザが使おうとしたときに、反応が早く感じられる。 レディ ブースト(ReadyBoost)  HDDは大容量なのだが、遅い。特にランダムアクセスとなると、10ミリ秒単位のオーダーになる。なぜならば、HDDは物理的にヘッドを動かさなければならないからだ。RAMは早いが、高価である。ときに、フラッシュメモリというものがある。これは、ランダムアクセスが、HDDの10倍は早い。しかも、それほど高くない。何ぞこれを使わざる。そういうわけで、Vistaは、フラッシュメモリを、メモリとHDDとの間のキャッシュとして使う機能がある。これはスワップファイルとして用いられると思っていたのだが、どうもMark氏の説明によると、Super Fetchで用いられるらしい。ディスク上の読み書きされたファイルを、フラッシュメモリ上にも記録しておく。この際、圧縮がかけられて、およそ二分の一の容量にした上で、AESで暗号化するようだ。不意にフラッシュメモリがはずされた場合でも、セキュリティを確保できるというわけだ。フラッシュメモリは、ランダムアクセスは早いが、シーケンシャルアクセスには、HDDより弱い。そんなわけで、もしキャッシュにヒットしたとしても、読み込みがシーケンシャルだと判断した場合は、直接HDDから読み込みに行くようだ。 レディ ブート(ReadyBoot)  XPにもある、起動を高速にする工夫だが、Visataでも一工夫されているらしい。 レディ ドライブ(ReadyDrive)  フラッシュメモリのキャッシュを付加した、ハイブリッドなHDDのこと。 Boot Configuration Database  Boot.iniはなくなった。これからはBCDの時代だ。EFIという新たな仕組みに対応したり、色々な改良のため、Boot.iniは廃止されたらしい。 スタートアップ プロセス(Startup Processes)  セキュリティ上の理由で、今までカーネルモードだったプロセスをユーザモードに移したなどの話。 Credential Providers  ログオン時の認証のUIなど。いままでもGINAという仕組みで、サードパーティのUIを作れたが、簡単にしたり、複数作れたりできるようになったらしい。たとえば指紋認証など。 Delayed-Autostart Services  起動からログオンのパフォーマンス向上のための仕掛け Shutdown  シャットダウンの際に、汚いサービスへの対応など Power Management  もはやWindowsは、アプリケーションを信頼せず、20秒以上、ハイバネート(スタンバイのこと)を待つことはない。  次回は、VistaのReliabilityとSecurityについてだとか。

2007-03-01

How C++0x looks like?

・decltype  簡単に言えば、sizeof演算子の型を返すものというべきか。コンパイラの実装にとっては、sizeofとほぼ同じといえる。
template < typename A, template B > decltype(A+B) func(A a, B b) { return a + b ; }
・auto  これは、型をよきように計らってくれる。たとえば関数の戻り値などは、コンパイル時に型が決まっているので、容易に推測できる。
std::vector< std::list< std::string > > v ; auto iter = v.begin() ;
 ここまでを踏まえての疑問、これは許されるのだろうか。当然許されるべきであると考えているのだが。
auto ret = func() ; std::vector< decltype(ret) > v ; v.push_back(ret) ;
・concept  これについては、ConceptC++チュートリアルが、非常に分かりやすかった。いままでconceptというと、単にテンプレートがらみのコンパイルエラーが読みやすくなるだけかと思ったが、Concept mapの強力さに驚いた。 ・rvalue reference  戻り値の型が、vector< int >な関数を、気軽に書ける機能。一時的な変数は、どうせすぐに死ぬのだから、内部のポインタを移してもかまわない。ポインタを移すだけならば、大量のコピーをするより早くなる。&&と、アンパサンドを二つ記述することで表現するらしい。サンプルコードは、実際に対応したコンパイラで試してからでないと、書けそうにない。  C++はどうなってしまうのだろう。ひとつ気になることがある。まともな日本語の参考書はでるのだろうか。現状で、まともにテンプレートについて学べる日本語の参考書を知らない。Modern C++ Designは、もはやModernではなくなっているし。Bjarne Stroustrupの書いた、枕代わりになる本の邦訳ならば書いてあるのかもしれないが、まえにちらと読んだ限りでは、ただでさえ読みにくい文章が、奇妙極まりない日本語に訳されていて、半ば睡眠薬となっていた気がする。