2013-12-29

C++03とC++11の違い: 文字列ライブラリ編

今日も今日とて、C++03とC++11の違いを解説する。今回は、文字列ライブラリー編だ。

変更: basic_stringをリファレンスカウントで実装することを禁止

C++が設計中の時代は、文字列を保持するストレージを文字列クラスで共有して、参照数を記録しておき、変更された時だけ書き換えるような実装が、主に使われていた。


class String
{
private :
    char * storage ;
    unsigned int * count ;

public :
    String()
        : storage( new char[100] ), count( new unsigned int(0) )
    { }

    // コピー時に共有する
    String( String const & s )
        : storage( s.storage), count( s.count )
    { count++ ; }

    // 誰も所有していなければ解放
    ~String( )
    {
        --count ;
        if ( count == 0 )
        {
            delete count ;
            delete[] storage ;
        }
    } 
} ;

このようなCOWによる文字列クラスの実装は、30年前はともかく、今となってはとても効率が悪い。なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。

変更: Small-string optimizationの許可

Small-string optimizationとは、文字列クラスの最適化手法のひとつである。多くの文字列クラスのオブジェクトは、短い文字列を扱うという点に着目して、あらかじめ短い文字列を、クラスオブジェクト自体に格納できるようにしておくのだ。


class String
{
    std::size_t size ;
    char sso[8] ;
    char * storage ;

    String( char const * ptr )
    {
        size = std::strlen( ptr ) ;

        if ( size > 8 )
        { // usual allocation
            storage = new char [ size ] ;
            std::copy_n( ptr, size, storage ) ;
        }
        else
        { // small-string optimization
            std::copy_n( ptr, size, sso ) ;
        }
    }
} ;

このように非常に短い文字列の場合はクラスオブジェクト自体で保持できるようにすれば、短い文字列ならば、動的にストレージを確保せずに保持できる。そして、文字列クラスの利用には、このような短い文字列のりようがとても多い。

small-string optimizationは、最近の文字列ライブラリの一般的な最適化手法になっている。従来の規格では、イテレーターが無効になる条件の都合上、small-string optimizationは、規格上許されていなかった。その制限はC++11で緩和された。

次回は、コンテナーライブラリー編だ。

2013-12-28

C++03とC++11の違い: 汎用ユーティリティライブラリー

今日も小粒な、C++03とC++11の変更点

変更: 最小限のガベージコレクションサポート

C++11にガベージコレクションは入らないが、GCを入れるための、変なビット演算でポインターの内部表現を戻したりしない、リーチ可能なポインターというものを規定している。これにより、C++03とC++11の規格に準拠したそれぞれのプログラムの挙動が変わる可能性が、規格上存在する。

変更: 標準ライブラリの関数オブジェクトは、std::unary_function, std::binary_functionから派生していない。

もう、C++11ではメタプログラミングが発達したので、このような基本クラスは必要がない。

次回はstringライブラリの違い

ACアダプターが断線

吉田寮で、うかつにもラップトップを起動したまま寝てしまった。起きた時にはラップトップの電源が落ちていた。不思議だ。ACアダプターをコンセントに挿しておいたのに、なぜバッテリーが切れるのだろうか。よくみると、コンセントが抜けている。なるほど、寝ている間に、誰かがつまづいたのだろう。

コンセントを挿しなおしてみるが、なぜか電源が入らない。不思議だ。挿し直すと入るが、またすぐに電源が途絶える。まさか・・・ACアダプターの断線。

そのまさかだった。ACアダプターが断線していた。線を動かしつつ断線箇所を探すと、ACアダプターとコンセントをつなぐ三叉のケーブルの中で断線しているようだ。ACアダプター本体は問題ないようだ。ああ、よかった。こちらなら、まだ何とかなる。

その日、寺町に行って、ジャンク品のケーブルを買った。新品は、ものすごく短いものしかなかったのだ。ただ、今から考えれば、単に電源タップを使うという運用でも良かったのかも知れぬ。このACアダプターから先のコンセントに差し込む方の線は規格化されているらしい。

やれやれ、はやくACアダプターも規格化してほしいものだ。思うに、もはやACアダプターに画期的な技術革新はないのではないか。なぜ規格化しないのか。ラップトップのACアダプターは、ひどいものになると、ある型番専用になっている。大量生産できないために値段も高い。ACアダプターが故障したために、使えなくなってしまったラップトップも多いのではないか。なんという無駄なことをしているのだ。

2013-12-27

ほっしー、連絡を乞う

連絡されたし by 江添亮 a.k.a 人柱

追記:連絡完了

XKCD What If: 致死量のニュートリノ放射ってどのくらいなの?っと

XKCD What If: 致死量のニュートリノ

超新星にどれだけ接近すれば、致死量のニュートリノ放射を浴びることができるの?っと

(物理屋の事務所から聞こえてきたセリフ)

「致死量のニュートリノ放射」というセリフは、いかにも奇妙だ。私はこのセリフを耳にした後、何度も首をかしげざるを得なかった。

もし、読者が物理屋でなければ、読者にはさほど奇妙に聞こえないかも知れない。そこで、この驚くべき発想の意味をちょっとわかりやすく書いてみよう。

ニュートリノとは、幽霊のような粒子で、この世界とはほとんど干渉しない。試みに読者の手の平を観察せよ。毎秒10兆個ほどのニュートリノが太陽から降り注いでいるのだ。

読者が膨大なニュートリノの存在に気が付かない理由は、ニュートリノというものは、通常の物質とほとんど干渉しないからだ。平均して、このような大量のニュートリノは、数年に一回ぐらい、読者の体の一個の原子と衝突する[1]。

[1]: 読者が子供であれば頻度が下がる。なぜならば、衝突すべき原子が少ないからだ。統計的に、筆者の初めてのニュートリノとの干渉は、10歳ぐらいのときに起きたはずである。

実際、ニュートリノはとてもこそこそしているため、太陽からの膨大なニュートリノは、地球全体を、何の影響もなく通り抜けてしまうのだ。ニュートリノを検知するために、人間は百トンもの物質で満たされた巨大なタンクをこしらえて、太陽からのニュートリノのひとつと、どうにか衝突してくれることを祈っているのだ。

これはつまり、粒子加速器(ニュートリノを生成する)が、ニュートリノビームを、世界のどこかの検出器に送りたいときは、検出器の方向にビームを向けるだけでいいのだ。たとえ、地球の反対側であったとしてもだ!

だからこそ、「致死量のニュートリノ放射」というセリフは、とても奇妙に聞こえるのだ。ありえないスケール同士の組み合わせだ。ことわざでいうならば、「羽で殴り飛ばされる」とか、「サッカー場の上までアリを詰める」[2]、といったところだ。もし、数学の素養があるのあらば、"ln(x)e"のような式を見たようなものだ。これは、文字だけ読めば、完全に意味をなさないというわけではないが、このような式を適用すべき状況が思いつかないのだ。[3]

[2]: それでも世界のたった1%程度の量のアリなんだけどね。

[3]: もし、数学科の一年生を苦しめたいのならば、この微分させた、ln(x)e dxについて質問してみるといい。1のようでもあり、他のなにかのようでもあるが、そうではないのだ。

このように、ニュートリノをたった一つの物質と作用させるだけの量を集めるのも難しいのだ。読者に影響を与えるほどの大量のニュートリノは、想像が難しい。

超新星(Supernovae)[4]は、そのような状況を提供してくれる。この問題を話してくれた物理学者は、超新星に関わる数字を推測するときの原則としては: どんなに超新星を大きなものと考えようが、超新星は想像よりもっと大きい

[4]: Supernovasでもいい。Supernoviiは非推奨。

このスケールの大きさを読者に認識させるための問題:

以下のいずれかが、読者の角膜に与えるエネルギーという点で、よりまぶしいか。

  1. 太陽と地球ほどの距離ほど離れた場所から観測した超新星
  2. 読者の眼球にくっつけて起爆させた水素爆弾

物理学者の原則を適用すれば、超新星のほうが眩しい。実際にそのとおりである。9桁もの差がある。

だからこそ、これが適切な質問になるのだ。超新星は想像できないほど強力で、ニュートリノは想像できないほど非力なのだ。いったい、どこまでいけば、このふたつの想像できないもの同士が打ち消し合って、人間のスケールで影響を及ぼすのか。

被曝の専門家、Andrew Karamの論文が、その答えを提供してくれている[5]。この論文は、超新星において、星の核が崩壊して中性子星になるとき、1057個のニュートリノが放出されると説明している(星のすべての陽子が崩壊して中性子になるのだ)

[5]: Karam, P. Andrew. "Gamma And Neutrino Radiation Dose From Gamma Ray Bursts And Nearby Supernovae." Health Physics 82, no. 4 (2002): 491-499.

Kramは、1パーセク[6]離れた場所におけるニュートリノ被曝量は、約0.5ナノシーベルト、あるいはバナナを一本食べた場合の500分の1の被曝量であると計算した。

[6]: 3.262光年、もしくは、ここからアルファケンタウリまでよりすこし短い。

[7]:xkcd.com/radiation

致死量の被曝量は約4シーベルトである。逆2乗の法則を使えば、被曝量を計算できる: \[ 0.5\text{ nanosieverts} \times\left ( \frac{1\text{ parsec}}{x}\right )^2 = 5\text{ sieverts} \] \[ x=0.00001118\text{ parsecs}=2.3\text{ AU} \] 2.3AUは、太陽と火星より少し遠いぐらいの距離だ

核が崩壊する超新星は、巨大な星に発生する。そのため、このような距離から読者が超新星を観測したならば、読者はおそらく、その超新星をつくりだした星の外層の中にいたはずだ。

ニュートリノ放射による被害という考え方は、いかに超新星が強力なものかを改めて思い知らされる。もし、読者が超新星を1AU離れて観測したとして、読者は何らかの方法で、発火、消失、そして何らかのエキゾチックなプラズマに変換されるのを免れたとしても、幽霊のようなニュートリノが、まだ読者を殺せるほどの量を持っているということだ。

もし十分に速ければ、羽は確実に読者を殴り飛ばせる。

2013-12-26

C++03とC++11の違い:言語サポートライブラリ編

江添とボレロ村上の京都C++勉強会は終わってしまったが、C++03とC++11の違いシリーズは続ける。

変更:operator newとoperator deleteの違い

C++11では、単体確保のためのoperator newとoperator deleteは、その他の確保関数、解放関数の基本的な関数として、呼ばれるようになった。

この変更の結果、以下のコード


#include <cstdlib>
#include <iostream>
#include <new>

void * operator new( std::size_t size )
{
    std::cout << "allocated" << '\n' ;
    return std::malloc( size ) ;
}

void operator delete ( void * ptr ) noexcept
{
    std::cout << "deallocated" << '\n' ;
    std::free( ptr ) ;
} 

int main()
{
    int * ptr = new int[3] ;
    delete[] ptr ;
} 

これを実行した結果は、

allocated
deallocated

となることが、C++11では保証されている。C++03では保証されていない。

つまり、C++11では、デフォルトの実装の配列型の確保関数、解放関数に、単数形のものが、使われることが保証されるようになったということだ。

変更:operator newがstd::bad_alloc以外の例外も投げるかもしれないようになった

C++03では、std::operator newには、動的例外指定、throw( std::bad_alloc ) が指定されていた。C++11では、動的例外指定は廃止予定になり、その意味も、単に例外を投げる可能性のある関数程度のものになったので、std::operator newが、std::bad_alloc以外の型を例外として投げる可能性が、規格上出てきた。そのための違い。

次回に続く。

2013-12-24

18日から24日までの日記

今回はかなり他人のプライバシーに土足で踏み込む内容なので、これでもかなり抑えて書いている。ここに記述された人で、問題があれば[email protected]まで、あるいは私につながる方法で連絡をくれれば、すぐに該当箇所を削除する(が、削除しても遅いだろうから、先に謝っておく。申し訳ない。)

18日

早朝、卓球ハウスで起床。すぐに出発。

今回、東京には用事で呼ばれているのだが、せっかくだから一週間ほどは滞在することにした。

どういう結果になるにせよ、これ以上C++の啓蒙を続けるには、他人に物理的に会ってC++を教育しなければならず、そのためには、プログラマーのいる場所に行くしかない。一極集中の日本では、プログラマーのいる場所といえば、ほぼ東京しかないのだ。なにかいい仕事があればいいのだが。

そのために東京に住まねばならないが、東京に縁もゆかりもない人間が、いきなり住んだところで、孤立するに決まっている。吉田寮のような場所が東京にもあればいいのだが。

すると、プログラマーを含めた多種多様な人間が集まりそうなシェアハウスにでも住むのが一番手っ取り早いわけだ。

というわけで、この機会に東京のシェアハウスを見て回ることにした。そこで、珍しく色々と計画と事前の予約を行った。

ギークハウス水道橋

ここには、ブインの提督、銀天すばる (SubaruG)さんが住んでいる。あいにくと、部屋はぜんぶ埋まってしまったようだ。

知り合いがいたからか、中に入ることはできたものの、やはり事前の調査通り、今のギークハウス水道橋から、吉田寮的雰囲気は感じられない。至って普通の平和なシャアハウスに成り下がってしまっている。これが普通なのだが、少し寂しい。当時から残っているという住人に昔の話を振ってみたが、昔は昔だったというだけで、とくに話したがらないようだ。全員働いているので、午前中のかなり早い時間に人はいなくなってしまった。すばる君の紹介があったからか、クッキークリッカー記事でブログが知られていたからか、「誰もいないけれどごゆっくり」とは言われたが、本当に誰もいないし、いてもどうしようもない平和で退屈な場所なので、すぐに次の場所に向かった。

ギークハウス文京護国寺

ギー水の崩壊に寂しさを覚えながら、私はギークハウス文京護国寺に着いた。ここは私から連絡したわけではなく、CyLydianの方から来てみないかと誘われたのだ。誘われた以上は行くのが礼儀というものだ。こちらは一転、すこし熊野寮のような感じがする。ただし、最近の熊野寮の閉鎖性も持ち合わせているようだ。ここは遊びに来るには面白そうだが、私の住むべき場所ではないように感じた。

ドワンゴ

先月の歌舞伎座tech#2で、ドワンゴに呼ばれて、C++14の新機能についての講演を行ったが、どうももう一度、今度は社内の講習会の講師として、C++の歴史について話してほしいということで、再び呼ばれた。

プログラミング言語の魔導書Vol.1で書いたように、私は以前からC++の歴史について興味があり、ひと通り調べている。基本的には、Bjarne Stroustrupの書いたHOPL-I, HOPL-II, D&Eが参考文献として使える。ただし、さすがに1990年代から2000年代前半にかけてのC++WG JPの事情はわからないため、この機会に、当時からC++標準化委員会に参加している人に色々と話を聞いた。それをまとめあげたのがこのスライドで、GitHubで公開している。

EzoeRyou/cpp-history

スライドでも書いたように、実に日本のC++事情は寒い。お寒い事情とは、すなわち、日本企業は独自のC++コンパイラーを社内の閉鎖的な環境で自作したかったが、それには技術力が足りないので、かわいそうな日本人でも実装できるC++のサブセット規格を作ろうとしていて、EC++の業界団体を立ち上げた。それがC++標準化委員会の日本支部と合流した。そのため、日本のC++標準化員会のスポンサーというのは、EC++という黒歴史のスポンサーだったわけだ。

当時のEC++関係者には気の毒だが、他ならぬBjarne Stroustrup本人にまでこう言われているのだ。

To the best of my knowledge EC++ is dead (2004), and if it isn't it ought to be.

私の知る限り、EC++は死んだ(2004年)、もし死んでいないとするならば、死ぬべきである。

Stroustrup: FAQ

もっとも、当事者によると、そういうわけではなくて、あくまで8-bit, 16-bit用のマイコンでも使えるC++のサブセット規格を策定したかったそうだ。

ただし、筆者はどうしても、まともなC++コンパイラーを自作できず(不自由ソフトウェアにこだわる以上必然なのだが)、だから日本人でも実装できる手抜きC++を作りたかったのではないかと邪推してしまう。

卓球ハウス

18日も一泊させてもらった。

さて、昨日今日と泊まっているこの卓球ハウスは、シェアハウスをやってみたい男たちが立ち上げた。狙ったわけではないものの、全員Web系のプログラマーだ。彼らはシェアハウスをギークハウスの混沌とした雰囲気にはしたくなかったらしく、まず、名前をギークハウスとはしなかった。曰く、「どうしても一度来てみたいという人がいれば拒むわけでないけれども、ギークハウスとは違い、平和にやりたい」とのことだ。そこで卓球ハウスと名づけた。名前が卓球ハウスなので、卓球台を調達した。その住所や住人は、Twitterなどの公の場で発言しているので、ここに書いても特に問題はないが、特に書くまでもない。

ただし、卓球ハウスは家の作りが豪華すぎるということだけは記しておいても問題にならないだろう。

卓球ハウスは普通の平和なシェアハウスだが、住人が全員プログラマーだけに、住んでみたくはある。

19日

卓球ハウスで起床、phaさんの住むところに向かう。

phaさんの住むところ

pha (pha)さんとは、ギークハウスの発起人だ。phaさんは元熊野寮生で、熊野寮の雰囲気を持つようなシェアハウス、すなわちギークハウスを立ち上げた。ギークハウスという概念は、もはや自治療も存在しない東京には新鮮だったらしく、だいぶ流行した。phaさん以外の人が、ギークハウスを名乗って、似たような性格のシェアハウスを建ち上げるようになった。ただし、他の人によって立ち上げられたギークハウスは、吉田寮や熊野寮を経験していない人によるものも多く、少し性格が異なっている。phaさん自体は、今は賑やかな生活にも嫌気が差し、静かな環境で暮らしている。結局、今のphaさんの住むところは、熊野寮の性格を表しているのではないかと思う。熊野寮と吉田寮は違うのだ。

phaさんの住むところは、今は少しネット上からは見つけにくい情報だ。詳細な住所は公開していない。厳格に隠している様子ではないとはいえ、積極的に公開もしていないようなので、ここではあえて具体的には書かないでおく。

phaさんの住むところには人懐っこい猫がいてとても和んだ。ただし、膝の上で眠りだすので動けなくなるのが、嬉しい悩みといったところか。

phaさんの住むところは、あまりにも静かすぎる。特に猫がいるので、それも人懐っこい猫がいるので、人懐っこくなくても猫がいるので、たまに遊びに来たいが、私の住むべき場所ではないように思う。

20日は、phaさんの住むところに一泊させてもらった。

20日

起床、猫が可愛い。ねこー、ねこー、ぬこー、ぬこー、ふぁぁぁ

ハッ、いかんいかん、これはまずい。いつまでも猫とたわむれていたいが、私は東京の滞在中に、なるべく多くのシェアハウスを見学して、住めそうなところを探さねばならないのだ。

私は吉田寮に入り浸っているので、必然的に気になるのは、妖怪ハウスだ。これは、吉田寮的雰囲気が崩壊して、今や退屈で平和な普通のシェアハウスに成り下がってしまった、ギークハウス水道橋に、崩壊前まで住んでいて、しかも元吉田寮生の平田朋義 (tomo3141592653)さんが、新たに吉田寮的雰囲気を構築するために立ち上げたシェアハウスだ。

ただし、私は20日には、ギークハウス秋葉原の見学も兼ねて、飲み会に出席しようと連絡していた。東京にいつまで滞在するかというのも問題だ。週末には帰ろうかと思っている。ここはギークハウス秋葉原には断りの連絡をいれて、最後に妖怪ハウスに行ってみようかと、平田さんに連絡を取ってみたところ、なんと、平田さんもギークハウス秋葉原の飲み会に出席するという。都合がいいので、今日はギークハウス秋葉原に行くことにした。

ギークハウス秋葉原

この場所に案内なしで地図だけをみて辿り着くのは不可能である。神田駅から5分というとても近い場所にあるのだが、絶対に案内なしにたどり着くことはできない。

ギークハウス秋葉原は、とても便利な場所にあるが、まだ始まったばかりで、今は住人が少ない。ただ、とても便利な場所ではあるので、住んでみたいとは思った。

さて、飲み会では様々な人が集まった。平田さんも来たので、近日中に妖怪ハウスに伺うということを伝えた。

平田さんは、飲み会を途中で抜けだしてクラブに行くという。私も誘われたが、私はクラブの喧騒は嫌いなので、やめておいた。私は音楽にもダンスにも興味はない。仮に聞くとしても、静かな音楽を聞きたいものだ。ただ騒がしいだけでは騒音でしかない。しかも、聞くところによれば、クラブはニコチン中毒者の巣窟であり、したがって常に忌まわしき煙が充満しているという。「誘われた以上、行くのが礼儀」とは書いたが、そんなドラクエで言えば毒の沼のような場所には行きたくない。ましてや、東京で住めそうなところを探すことには直接関係ない。

ただし、クラブには多種多様な人間が集まるであろうことは確かで、もし、静かで過密しておらず禁煙なクラブがあれば行ってみたい気はする。

さて、その後、Hanabiというカードゲームをした。このゲームは、全員で協力して花火を完成させるゲームだ。競争ではない。ただし、自分の手札は見ることができないので、他人に自分の手札の情報を教えてもらわなければならない。このゲームは、とても面白かった。競争させずに、ここまで面白いゲームが設計できるとは、フランス人もなかなかやるではないか。このゲームはいずれ買おう。

20日はギークハウス秋葉原に泊まった。

21日

卓球ハウスでカタンを行った。同日宿泊。

22日

起床。妖怪ハウスに向かう。

妖怪ハウスは、元吉田寮生の平田さんが、吉田寮を再現すべく努力しているだけあって、だいぶ吉田寮に近かった。ここはとても居心地がいい。住人のうち、プログラマーの割合こそ低いものの、ここに住んでいれば、多種多様な人と会うのに困ることはないだろう。

ただし、ここは吉田寮ではなく、平田ホスピタルである。

その肝心の平田さんは、今日はここにはいない。どうも、渋ハウスでイベントをやるらしく、そこに参加しているそうだ。渋ハウスもだいぶ開かれたシェアハウスであると聞いているので、多種多様な人と会えるのではないかと思う。ただし、聞けばイベント会場は、よその場所を貸しきって行うらしく、渋ハウスではないそうだ。東京で住める場所を探すという目的からは外れるので、行くのはやめた。

渋ハウスにも行ってみたいが、どうも聞けば、美術、芸術系の住人ばかりで、プログラマーはほとんどいないらしい。実際に現地を見ていない以上、まだわからないが、おそらく私が住むには適さないのではないだろうか。

22日は妖怪ハウスに泊まった。

23-24日

当初の予定では、週末頃に帰るはずだったが、妖怪ハウスの居心地がいいのと、年末に吉田寮に一週間ほど滞在してみたいという学生がいるので、案内がてら同道して京都に帰るため、もう少し東京に滞在することにした。

この妖怪ハウスには、将来的には住んでみたいと思うので、とりあえず住人に受け入れられるかどうかをみるために、今週もまだ何日か滞在しようと思う。あるいは、まだ行っていないシェアハウスを見学してみるべきか。

年末には帰る予定だ。

GNU/LinuxでMac OSのバイナリを動かす互換レイヤーの開発が停滞

[Phoronix] Hope Seems Lost In Running OS X Binaries On Linux

以前、本の虫: Mac OS XのバイナリをGNU/Linuxで実行するソフトウェアで取り上げた、Darlingという、Mac OSのバイナリをGNU/Linuxで実行する互換レイヤーだが、どうやらここ数ヶ月ほど、何の活動もないらしい。主要な開発者も去り、どうやら死んだようだ。

Wineもそうだが、この手の互換レイヤーは、あまり好ましくない。なぜならば、バイナリのみで提供される不自由なソフトウェアの実行を容易にしてしまうからだ。まだ盲目的にWindowsを使っていた頃は、Wineについて詳しく調べていたのだが、その知識は、未だに役立っていない。結局、Windowsでどうしても動かしたいソフトウェアなど、ゲームぐらいしかないのだ。その肝心のゲームも、いまはまるでつまらないときている。もはやWindowsの時代は終わったのだ。

xkcd: 永続性

xkcd: Permanence

[!] ネットワーク設定

システムのホスト名を入力してください

妻「ずっとその画面眺めてるわね」
夫「いいサーバー名を決定するのは大事なんだ」

妻「でもうちの子の名前は15秒ぐらいで「キャロライネ」に決めたじゃない」
夫「でも、これはサーバーだぞ!」
夫「それに、あのままほっとくと、お前「コーマクガイ」とか名づけそうだったじゃないか」
妻「あら、いい麻酔じゃない」

ホスト名は人の名前より変更するのが難しい。

テンプレートの実体化の実装方法とODR違反について

問題

以下のC++コードを考える。

int plus( int a, int b )
{
    return a + b ;
}

double plus( double a, double b )
{
    return a + b ;
}

このC++コードは、int型とdouble型以外、コードはほぼ同じである。

しかし、ほとんどのコンピューターではint型とdouble型は操作方法が異なるため、この2つの関数は、全く別のコンピューターが処理できるコードに変換される。

ところで、古典的なC言語やC++コンパイラーの実装方法として、ソースコードのファイルをそれぞれ、一つ一つの翻訳単位としてコンパイルし、翻訳単位ごとにオブジェクトファイルを生成し、リンカーで複数のオブジェクトファイルを結合(リンク)して、単一のプログラムを生成するというものがある。

よくある実装では、オブジェクトファイルは、その翻訳単位では定義されていないの関数や変数などを、その名前を「シンボル名」として、未解決のまま参照しておき、リンカーがすべてのオブジェクトファイルが揃った時点で解決する。

// f.cpp

// 定義
void f() { }
// main.cpp

// 宣言
void f() ;

int main()
{
    f() ; // fは定義されていない
}

C++規格では、単にソースファイルとか翻訳単位とか、複数の翻訳単位を合わせて単一のプログラムにするなどと規定されているだけでが、典型的な実装では、このようなソースファイルを分けて、別々にコンパイルして、オブジェクトファイルを生成し、後でリンクして単一のプログラムにすることを、俗に、「分割コンパイル」と呼んでいる。

またC++では、仮引数の型が違うが同じ名前の関数を、複数定義できる。そして、呼び出す際に、型の一致度の優先度を判定して、最適なものを呼び出す。これをオーバーロード解決(Overload resolution)という。

// 別の翻訳単位で定義されている
void f( int x ) ; // #1
void f( double x ) ; // $2

int main()
{
    f( 0 ) ; // オーバーロード解決、#1
    f( 0.0 ) ; // オーバーロード解決、#2
}

しかし、これは古典的なコンパイルしてリンクという実装では、どのように実現すればいいのだろうか。どちらも同じ名前である。

C++の典型的な実装では、シンボル名に関数のシグネチャを埋め込む。これを、名前マングリング(name mangling)という。

// 名前マングリングの例
void f_int_( int x ) ;
void f_double_( double x ) ; 

int main()
{
    // オーバーロード解決済み
    f_int_( 0 ) ;
    f_double_( 0.0 ) ;
}

このように、シンボル名にシグネチャを埋め込んでしまえば、賢くない古典的なリンカーでも、単にシンボル名の一致だけでリンクできる。C++では、名前マングリングの詳細は規定されていない。シンボル名が規定されていないのと同じだ。

さて、テンプレートの場合はどうか。

template < typename T >
T plus( T a, T b )
{
    return a + b ;
}

int main()
{
    f( 1, 2 ) ;
    f( 1.0, 2.0 ) ;
}

関数テンプレートは、実引数推定(Argument Deduction)という機能により、テンプレート実引数を推定できる。これはつまり、以下のように呼ぶのと同じ意味である。

int main()
{
    f<int>( 1, 2 ) ;
    f<double>( 1.0, 2.0 ) ;
}

テンプレート実引数は、< >という文法で指定する。関数の実引数が( )という文法で指定することと比較すれば、わかりやすいだろう。

テンプレート自体は、オブジェクトコードを生成しない。テンプレートは、コンパイル時に具体的なテンプレート実引数を与えられて、その実引数に対して、実体化する。テンプレートが実体化すると、あたかもコードを手で書いたかのように、実態が生成されて、使われる。もちろん、これにも名前マングリングが使われる。

さて、テンプレートも分割コンパイルしたいと思うだろうが・・・残念ながら、実装上の都合で、色々と難しいのだ。

テンプレートは、コンパイル時に実体化する必要がある。しかし、翻訳単位ごとに分割されていると、その実体化ができないのだ。

// plus.cpp

// 定義
template < typename T >
T plus ( T a, T b )
{
    return a + b ;
}
// main.cpp

// 宣言
template < typename T >
T plus( T a, T b ) ;


int main()
{
    plus( 1, 1 ) ; // 実体化の生成が必要
}

今、plus.cpp、main.cppが、それぞれ別の翻訳単位であるとする。main.cppは、テンプレートplusの宣言から、テンプレートを実体化しなければならない。しかし、実体化するには、テンプレートの定義が必要だ。

実装方法

翻訳単位を超えたテンプレートの実体化を、どのように実装するかというのは、とても難しい問題だ。とくに、古典的な翻訳単位ごとにコンパイルしてリンクするというコンパイラーの場合、翻訳単位ごとに完全な定義が与えられていなければ、コードの実体化ができないという問題がある。

CFrontの実装

Bjarne StroustrupによるC++のリファレンス実装は、Cコードを出力して、Cコンパイラーでコンパイルする都合上、当時の古典的なコンパイラー技術で実装する必要があった。

名前マングリングは、そのために考案された。古典的なリンカーは、単にシンボル名の文字列一致だけをみてリンクするので、シンボル名にテンプレート実引数を埋め込んでおけば、その実体化へのリンクができる。

CFrontの実装は以下の通り

  • シンボルに名前マングリングする
  • テンプレートを実体化せずにコンパイル
  • 実体化していないために発生するリンクエラーメッセージをパース
  • 実体化の必要のあるテンプレートの特殊化を抽出
  • テンプレートの実体化を行う

この処理は、リンクエラーを吐かなくなるまで、繰り返し実行する必要がある、なぜならば、テンプレートを実体化した結果、別のテンプレートの実体化が必要になるからだ。

template < typename T >
struct A { } ;

template < typename T >
struct B
{
    A<T> a ;
} ;

CFrontの、リンクエラーを用いたテンプレートの実体化の実装は、とてつもなく遅かった。ある大学は、他の方法で実装されたコンパイラーならば数時間でコンパイルできるコードが、CFrontでは一週間もかかると報告した。

SunのC++コンパイラーの実装

SunのC++コンパイラーは、いかにもSunらしい実装をしている。

  • プログラムを構成するすべての翻訳単位で共通のデータベースを用意
  • ある翻訳単位でテンプレートの実体化が必要ならば、データベースを参照
  • もし、すでに最新版の実体化が存在すればそのまま利用
  • もし、データベースに実体化が存在しなかったり、最新のソースコードより古く生成されたものであれば、実体化してデータベースに格納

いかにもSunらしいデータベースを活用した実装だ。この実装は、技術的には極めて自然であり、並列コンパイルによるコンパイル時間のスケールも特に問題はない。

問題といえば、実装が難しいことと、Makefileのような単純にファイルスタンプだけ比較するような古典的なビルドシステムを使うのが難しいということだ。

BorlandのC++コンパイラーの実装

この中で、彗星の如く現れたのがBorlandのC++コンパイラーだ。

  • テンプレートの定義をヘッダーファイルに書く
  • テンプレートの実体化を必要とするすべての翻訳単位から#include
  • 翻訳単位ごとに独立してテンプレートを実体化
  • リンク時に重複を取り除く

この実装では、リンカーが単にシンボル名の一致で参照を解決するものから、重複を取り除くということまでやるようになったので、古典的なリンカーとは言えないかも知れない。しかし、当時もリンカーはすでに相当複雑になっていたわけだ。

どうせリンク時に重複を取り除かれるのに、同じテンプレートを翻訳単位ごとに実体化するのは、一見すると非効率的のように思われるが、パフォーマンスは全く問題なかった。

そして何よりも、実装が簡単だった。

しかし問題になるのは、ODR(One Definition Rule)[§3.2]だ。単一定義の原則だ。C++では、定義はひとつしか存在できないのだ。

// file1.cpp

template < typename T >
struct S { } ;
// file2.cpp

// 定義の重複
template < typename T >
struct S { } ;

int main()
{
    S<int> s ;
}

いま、file1.cppとfile2.cppがひとつのプログラムを構成するソースファイルであり、ソースファイルごとに翻訳単位が存在するとすると、当時のドラフト規格では、このコードは違法となる。

Borlandが最初に考えだしたこの実装方法を、規格上許容すべきかどうかは、標準化委員会でもかなり揉めた。ある者は、Borlandの実装方法はODRに明確に違反しており、本質的に汚いので、規格で禁止すべきだと主張した。また、この実装では、テンプレート定義はすべてヘッダーファイルに書いて、ソースファイルに字句的に取り込まなければならない。非テンプレートコードのように、宣言と定義を分けることができない。実体化を必要とするテンプレートであっても、宣言と定義を分けられるべきだという主張もされた。

とはいえ、Borland式の実装はとても実装が簡単で、多くのC++コンパイラーがBorland式の実装を使い始めた。そのため、さすがに現実を無視することもできず、規格で特別に、主にテンプレートに限り、別の翻訳単位に現れるまったく同じトークン列、全く同じ意味の定義を、特別にODR違反から除外することを許可した[§3.2 paragraph 6](実際にはもっと複雑に規定されている)

全く同じトークン列を保証するには、ヘッダーファイルとして書いて、#includeで取り込めばよい。まったく同じ意味とは、テンプレートの特殊化で呼び出す関数などが、テンプレートの実体化やオーバーロード解決を経た後でも、すべての翻訳単位で、同じでなければならない。

// file1.cpp

void f( int ) { }

// 同じトークン列
template < typename T >
void g()
{
    f( 0 ) ;
}
// file2.cpp

void f( long ) { }

// 同じトークン列
tempalate < typename T >
void g()
{
    f( 0 ) ;
}

このような複数の翻訳単位からなるプログラムは、違法である。

先週、この問題を解説する必要があったが、なかなかこのような問題は口頭で解説するのが難しく、おそらく正しく理解してもらえなかったと思うので、ブログに書いておくことにした。

実は、これと似たような歴史的経緯を、株式会社ロングゲート - プログラミングの魔導書 ~Programmers’ Grimoire~ vol.1で書いた「C++の歴史」でも解説している。そういえば、私は魔導書のVol.3には関わっていない。今回、C++色は薄かったようだ。Vol.4はどうなるのだろうか。

ミハイル・カラシニコフ死去

BBC News - AK47 assault rifle designer Kalashnikov dies at 94

AK-47として知られている7.62mm小銃を設計した、Михаил Тимофеевич Калашников(ミハイル・チモフェエヴィチ・カラシニコフ)が、94歳で亡くなった。

アラン・チューリングに恩赦

BBC News - Royal pardon for codebreaker Alan Turing

1952年、ホモセクシャリティ罪で検挙され、保護観察下におかれ、しかも化学的去勢を行われた、暗号解読者にして、コンピューター科学にも多大な貢献をしたアラン・チューリングに対し、ホモセクシャリティ罪に対する恩赦が与えられた。

あまりにも遅すぎる。

2013-12-23

人との再会は難しい

今、筆者は東京にいる。東京は、人の集まる場所である。実に、大勢の人間が地方からやってくる。

結局、一極集中は効率的なのだろう。それに、地方には仕事がない。

ということは、田舎に住んでいた頃の私の昔の同級生は、東京に住んでいる可能性があるわけだ。

せっかく東京に滞在しているのだから、そのような昔の同級生だった者と再会し、つもる話をもし、成功したのか失敗したのか、近況を聞きたいものだ。

筆者はすでに、京都に住んでいて、昔の友人と再会したことがあるのだ。それは友人側からこのブログをみて連絡が来た。

実は、ネット上で検索した結果、そういう人間が一人だけ、少なくとも去年は東京で働いていたらしい。特別に仲が良かったわけではないが、当時、同じ町内に唯一住んでいた同級生なので、印象には残っている。

ただし、連絡方法がない。いや、あるにはある。実家に紙の手紙を送るという方法がある。しかし、そこまでして会いたいかというと、なかなか難しい。

その同級生が女であることも、連絡を躊躇させる要因となっている。

2013-12-22

アニメにおけるセルシェーディングの利用について

セルシェーディング技術は、非常に発達している。3Dモデルを描画する際、あえて似通った領域を単色で塗りつぶすようにするのが、極端な簡略化した説明だが、とにかく、いかにも3DCGという奇妙な違和感を消し、まるでアニメ塗りのような描画ができる。

ゲームでは、セルシェーディングはよく使われている。例えば、不自由なゲームだが、最近のゼルダの伝説や、Borderlandsといったゲームだ。

では、アニメではどうなのか。実は、意外と積極的には使われていない。

たとえば、プリキュアというアニメでは、エンディングの映像に、セルシェーディングが使われている。非常に高品質で、しかもヌルヌル動く。プリキュア本編はまったくつまらないのだが、、エンディングだけはとても面白い。しかし、本編には、ごく一部の、動きの激しいシーンなどにしか使われていないという。しかも、手で修正を加えた上、フレームも極端に間引いているという。しかし、現に修正をくわえずともそれなりの品質になっているではないか。なぜフレームを間引かずに、大規模な手動の修正も行わずに、そのまま使わないのか。

なぜだ。なぜ手動風の劣化を加える必要があるのだ。なぜぬるぬる動くアニメにしないのだ。

プリキュアを見ていると、明らかに全面的に手で書かれた場所が出てきて、そのような場所は、フレーム単位でみると、とても作画品質の低いことがある。これは、俗に「作画崩壊」と呼ばれている。それに、肝心のアニメーション自体も貧弱だ。しかし、セルシェーディングならば、常に一定した品質を提供できるではないか。なぜセルシェーディングにしないのか。

ある者曰く、ぎこちないアニメーションのほうがむしろ自然なのだという。しかし、トムとジェリーは、ヌルヌルと動くアニメーションで、それでいて最高に面白いではないか。

多くのアニメでは、徒手格闘が出てくる。そういうシーンを、ぬるぬる動くアニメーションに、なぜしないのか。映画マトリックスのようなものがある以上、そこそこの品質でぬるぬる動くアニメーションのほうが素晴らしいと思うのだ。手動で描くと、作画は悪いはアニメーションは悪いはと、劣化でしかないと思うのだ。

あるいは、映画は24 Frame Per Secondで撮影しないと、映画らしくならないという話と似たようなものなのだろうか。つまり、我々が、映画なら24FPS、アニメなら作画崩壊貧弱アニメーションに慣れてしまっているので、あまりにも高品質すぎる物を見せられると、違和感が生ずるのだろうか。

しかし、現に私は、プリキュアに関しては、本編の人の手による悲惨な劣化作画と見るに耐えない劣化アニメーションよりも、、エンディングのセルシェーディングされてヌルヌル動く映像のほうが、圧倒的に高品質であると感じる。圧倒的に魅力がある。もし本編がこのように作られていたならば、ぜひとも見たいと思う。現に、プリキュア本編は見るに耐えない内容であったが、エンディングの映像だけは食い入るように眺めてしまった。なかなか悪くないセルシェーディングだからだ。

あるいは、人の手で描かれたものを尊ぶ風潮でもあるのだろうか。しかし、それならばもっと抽象的で極端なデフォルメの絵にすればいいわけで、プリキュアはまだその抽象度とデフォルメ度が十分ではない。それよりは、セルシェーディング技法に技術的観点から興奮すべきではないのか。

もちろん、エンディングは繰り返しつわれる短時間の映像だから、セルシェーディングした後に、手動でフレームごとに修正を加えているのかも知れない。しかし、私は近年のセルシェーディング技法の発達を知っている。もちろん、セルシェーディングもそのようなシェーダーを書くのは職人技だが、フレームごとにひたすら手動でやるよりも、よほど筋のいい職人技だ。一度素晴らしいシェーダーを書けば、それにより全体が向上する。

そういう意味では、アニメは完全にセルシェーディングにして、ビルドして映像生成という形にすべきではないのか。すなわち、ソフトウェアだ。ソフトウェアである以上、自由ソフトウェアにすべきだ。そうすれば、稚拙な3Dメッシュが直されたり、シェーダーが改良されたりするのではないか。

いい加減に人の手で努力しただけのものを評価するのは、やめようではないか。もはや、写実画は写真に負けている。人間がまだ優位に立てると安心しているデフォルメの世界だって、例えばアニメ塗りのようなものは、セルシェーディングで近似できる。セルシェーディング技法は今後もますます発展することに疑いはなく、人間の優位性はいよいよ危うい。

将来は、ピカソのような絵や、デフォルメ化された3Dメッシュなども、自動的に生成できるようになるだろう。

私の観測できる範囲では、プログラマーとアニメの親和性は高い。私はアニメが好きではないから、これは不思議なことだ。私には、なぜ彼らがアニメを尊ぶのか、理解できない。現行のアニメが、単に人の手による単純作業で作られている。アニメ制作者が安く買い叩かれているのは、やはり、ある程度の画力があれば、代わりはいくらでもいるような単純作業だからだろう。

変えようではないか。現状を。アニメは技術者が作ればいいのだ。作画は3Dメッシュに取って代わられる。塗りはセルシェーディングに取って変わられる。高品質な3Dメッシュを作成するのは困難だが、一度作成してしまえば、後はアニメーションを作ればどのようなシーンもアニメーションできる。破綻しない自然な塗りをシェーダー言語で記述するのは困難だが、一度書いてしまえば、後はどのようなシーンでもレンダリングできる。

怠惰は美徳である。機械的な作業は機械に任せようではないか。もし、ある手動作業が自動化できるとするならば、我々はむしろ自動化するための準備に労力を注ぐべきなのだ。そうすれば、後は全て自動化される。我々人間は、機械を作るべきなのだ。その身を機械におとしめてはならない。

なるほど、私がアニメを好まない理由が、今にしてわかった。アニメは手動の単純作業だから感動しないのだ。そして、その映像の描画方法、すなわちソースコードが公開されていないから嫌悪するのだ。ああ、残念ながら、この考え方はあまりにも先進的すぎる。おそらく、数百年は理解されないことだろう。

ただし、2013年にこのような考えを持つ進んだ一個の人間がいたということは、ここに記しておく。

2013-12-21

Google、Chrome Web Storeから多目的の拡張を禁止する

GoogleはChromium Blogで、Chrome Web Storeから、複数の目的を有する拡張を禁止する発表を出した。

Chromium Blog: Keeping Chrome Extensions Simple

本日、我々はChrome Web Storeポリシーの変更を告知する。Chrome Web Storeの・拡張は、必ず、狭く簡単に理解できる単一の目的を有さなければならない。これはChrome拡張システムの意図であるが、すべての拡張はこの理想に従っていない。奴ら、多目的拡張(mutli-purpose extensions)は、ブラウザーのUIをごちゃごちゃとさせ、Webブラウジングを愚鈍にし、時には悲惨なことになる。我々はこの問題を修正し、ユーザーにブラウザーの支配力を与えるために、今回のポリシー変更を行った。

簡潔で高速なブラウジング体験は、Chromeのはじめからの、基本理念である。簡潔性は我々にとって重要なことで、その理由は、ブラウザーはとても複雑になり、重量級のユーザーインターフェース(俗に"chrome"(ブリキ化)と呼ばれている)を持っているからだ。この複雑なUIは、ブラウザーのそもそもの存在理由である、ページ内のコンテンツから注意を空してしまう。"Chrome"という名前は、我々は「コンテンツ」に注力したいというこの理念からきている。

現在、ブラウザーの重量化に強力に貢献しているのは、万能ツールバーのような拡張だ。ユーザーが複数のそのようなツールバーをインストールした結果は、悲惨なものになる。

我々の簡潔性の理念を維持するため、我々は異なるアプローチをとることを決定した。Chrome拡張は自然に簡潔で単一の目的用になり、単一のbrowser actionか単一のpage actionという、単一の可視UI「サーフェイス」しかサポートされない。ツールバーは設計上サポートされず、ユーザーはこれによりブラウザーに追加する機能について一層のコントロールを得ることとなる。

残念ながら、一部で、このような設計を技術的に矯正できない。 content scriptにより、拡張の開発者はページに対する完全なコントロールを得、結果として、どんなUIでも実現できる。たとえ、ツールバーをページに作成するような機能であったとしてもだ。他には、content scriptを使って、多数の機能がごちゃまぜになったような、どのような拡張とも分類しがたいものをつくりだす。多くの場合、Chrome Web Storeは、ある拡張が変な挙動をしていることを、低評価により示しているが、そうでもない場合もある。

なお悪いことに、拡張がローカルのコンピューターに、間接的に読み込まれた時(たとえば、他のインストールしたソフトウェアに同梱されていたなど)、ユーザーはChrome Web Storeの恩恵を受けることができない、そのため、望まない機能や低評価の拡張のインストールにユーザーが同意したことに気が付かないことがある。

このため、当初の単一目的の設計を強制させるため、Chrome Web Storeのポリシーを変更した。我々は、これにより既存の拡張に大きな変更が必要になることを承知している。一部の拡張は、複数の拡張に分離する必要があるだろう。開発者は、我々が追加した、拡張への送金方法を簡単にする方法に変えて、別の方法による課金方法に切り替えないといけないだろう。これらの変更には実装に少し時間がかかるため、2014年6月まで強制を見送る。新しい拡張については、このポリシーは直ちに適用される。

Googleもだいぶ邪悪になってきたようだ。ある拡張がどう実装されようとどうでもいいわけで、これはユーザーにコントロールを与えるなどというのは詐欺もいいところだ。問題の本質は、Windowsにまともなパッケージマネージャーがないことに起因すると思うのだが。

Google announces ban on "multi-purpose" Chrome extensions | ZDNet

Google announces ban on "multi-purpose" Chrome extensions | Hacker News

2013-12-19

2013年12月16日から17日の日記

16日

いつも通り、吉田寮で起床。最近、私は吉田寮に入り浸っている。吉田寮は人を選ぶが、私にとっては、とても居心地のいい空間なのだ。

今日は、はてなのセミナールームを借りて、勉強会を行う。また、狂える中3女子ボレロ村上さんを案内しなければならない。ひとまず自宅に戻って身支度をした。

午前中は、修理に出していたJ-PRESSのダッフルコートを取りに行った。これから一週間ほど東京に行くので、なにかまともなコートがほしいと思っていたのだ。実家には、父親があまり着ていない昔のコートがある。もう30年ほど前に、当時7,8万で買った、いいコートだ。今は、もはやこんないいコートは金を出しても買うことができないという。何でも、復刻版があるそうだが、父親いわく、どうも劣化しているとのことだ。合皮のような革で、水牛のツノもまるでプラスチックのような見た目だという。

このダッフルコートは、生地の端を布で覆っているのだが、その布がボロボロになってしまっている。私はそれでもいいと思うのだが、父はこだわる人間で、着るならばと修理に出すことにしたのだった。

ただし、これを修理するには、一度服をバラバラにして、再び縫い合わせなければならない。技術的には可能なのだが、とても手間がかかる作業だ。材料費こそ三千円程度なのだが、あまりにも手間がかかるため、結局3万円ほどかかってしまった。三万あれば、普通のコートは買えるだろう。しかし、このコートは買えない。このコートは三万出してまで治す価値のあるコートだ。

王将で餃子を食べて家に帰ってみると、なんと、ボレロ村上さんが、予定より早く、すでに京都駅に着いているという。私は急いで京都駅に向かった

聞説、ボレロ村上さんは長髪で作務衣を着用しているという。京都駅でそのような人物を探すが見つからない。はて、どうしたものか。携帯電話を持たない私にとって、唯一の通信手段はラップトップとモバイルWiFiルーターだ。そのような大掛かりな通信装置を広げるのは面倒だが、見つからない以上、やるしかない。と、そう思いかけた瞬間、とても筋骨たくましい男が声をかけてきた。なるほど、最近の中3女子はだいぶ屈強な体格をしているのだな。長髪ではあるものの、作務衣ではない。まあ、今の季節に作務衣はいかにも寒すぎる。

我々はバスに乗って吉田寮へと向かった。吉田寮は人を選ぶ場所である。果たしてボレロ村上さんは吉田寮を受け入れることができるのか、それは気がかりではあったが、この漢であれば、問題はないだろう。

さて吉田寮に到着し、暖房の入った部屋に通したボレロ村上氏は、おもむろに外套を脱ぎ始めた。するとみよ、なんと氏は、外套の下に作務衣を着ているではないか。今にして筆者は、氏の陶芸家としての姿を目にしたのだ。

さて、しばらく吉田寮でだらだらと過ごし、たこ焼きを食べた後、我々ははてなのセミナールームに向かった。そして、C++の勉強会を開催した。

勉強会というものは、今、とても流行している。筆者もC++の啓蒙活動をしている身で、過去に二回、勉強会で発表したので、やはりここは、勉強会を主催してみるべきだと考えたのだ。

結論だけ書くと、勉強会を個人で開催するのはとても難しい。今回は、はてなが場所と人を提供してくれたので、便利にもUstreamによる配信付きの勉強会を開くことができたが、長期的には色々と工夫しなければならない。

詳しい内容については、以前の記事を参照してほしい(もちろん、すでに終わった勉強会であるので、申し込みはできない)

本の虫: 江添とボレロ村上の京都C++勉強会、開催の告知と参加者募集のお知らせ

本の虫: 江添とボレロ村上の京都C++勉強会のスライド資料

本の虫: 江添とボレロ村上の京都C++勉強会を終えて

さて、勉強会を終えて、ボレロさんを囲んで吉田寮で鍋をつつくことにした。ボレロさんは吉田寮との親和性が高く、初日にコタツで寝るという離れ業を披露してみせた。

17日

吉田寮で起床、というか昼ごろまで雑談

ボレロ村上さんは、本当に吉田寮との親和性が高く、我々が大声で雑談している中、ぐっすりと熟睡していた。なかなかに常人のできることではない。

その日の雑談はとても面白く、もっと話していたかったのだが、残念ながら私は用事があるので、昼ごろに抜けて、身支度をし、夕方過ぎに東京へと向かった。

明日は朝早くから色々と用事があるので、その日は早めに就寝。

続く

Ubuntu 14.04がTRIMをデフォルトで有効にする

[Phoronix] Ubuntu 14.04 Finally Enables SSD TRIM By Default

Ubuntu 14.04が、SSDのTRIMをデフォルトで有効にするそうだ。

Linuxカーネルは2.6.33からTRIMをサポートしているが、これを有効にするには、discardマウントオプションを指定する必要がある。Ubuntuは、デフォルトでこのマウントオプションを有効にしていなかった。

「十分なテスト」の結果、Ubuntu 14.04では、TRIMをデフォルトで有効にする決定がなされた。

2013-12-17

clang_completeのvimプラグインの開発が停滞中

Clang_completeという、Clangを使ったCファミリー言語の静的解析ツールがある。これは、Clangの素晴らしいフロントエンドをそのまま使い、高度で規格準拠な名前補完機能を提供してくれるツールだ。

このclang_completeを、Vimという最高のテキストエディターから使えるようにするプラグインがある。

Rip-Rip/clang_complete

ところが、このプロジェクトは、最近開発が停滞しているようだ。例えば、以下のような簡単な修正のPull Requestすらマージされずに半年放置されている。

Fixup jumpToLocation loc.file is NoneType by visitor83 · Pull Request #336 · Rip-Rip/clang_complete

Silex commented

@xaizek: このプロジェクトの状況はどうなっているんだ? この程度のものはマージされるべきだろ。@Rip-Ripのアクティビティをみるに、最近は何もしていないみたいだな。

xaizek commented

@Rip-Ripのアクティビティは、この春からみてないな。たぶん、今はプロジェクトを保守する時間もないんじゃないか。

さて・・・いずれVimのプラグインの開発方法も学ばなければならないな。

江添とボレロ村上の京都C++勉強会を終えて

江添とボレロ村上の京都C++勉強会が、無事終了した。

今回の勉強会にあたって、一番苦労したのが、場所の確保である。勉強会を開催するには、数十人を格納できる場所がなければならない。さらに、単に場所だけでは不十分で、椅子、テーブル、プロジェクター、電源、無線LANが提供されていなければならない。

勉強会での発表には、スライドを映す必要があるので、プロジェクターは必須である。

さらに、聴衆もラップトップは使いたいであろうし、インターネットにも接続したいだろうから、電源と無線LANも提供されていなければならない。となると、椅子とテーブルも必要である。

勉強会の主催は相当に面倒だが、やはり、変化しなければならないと決めた以上、新しいことをやらなければならないのだ。

私は人前でスカスカのスライドを映して口頭で60分ほど話すことによる教育効果には疑問だ。まず、スライドというのはそれほどの情報量を含めることができない。たまに、アホなスーツが情報のぎっしり詰まったとても読みづらいスライド資料を使うことがあるが、あんなものは到底読めたものではない。それゆえ、スライドは自然とスカスカとなる。それに、口頭で使える情報は、とても伝達効率が悪い。まず、人間の話す速度は遅いという問題がある。それに、私は弁舌の徒ではない。

したがって、勉強会というのは、具体的な詳細を解説するのではなく、こういうものもあるという紹介程度の内容にならざるを得ない。ことC++においては、その情報さえ、日本語では不足しているということもあるだろうが。

とにかく、勉強会に使える場所を確保しなければならない。色々と探したあげく、京都駅の近くに、プロジェクターと電源と無線LANがついて、一時間三千円で借りられる部屋を見つけた。

京都の貸し会議室・レンタルスペース|ベーコンラボ

収容人数が、テーブルを出すと20人、椅子だけで最大38人ぐらいと、ちょっと狭いのだが、京都駅の近くなのでわかりやすいし、何より、プロジェクター、電源、無線LANの条件を満たす部屋というと、京都市内は本当に少ないのだ。

当初はベーコンラボを使おうと思っていたのだが、にわかに京大の教室を借りるとか、はてなのセミナールームを借りるなどという話が出てきた。

京大の教室は、土日も借りられるし、なにしろ大学の教室なのだから、プロジェクターと電源と無線LANはあるし、それに100人ぐらいが入れる大部屋もあるという点で、とてもすばらしいものだ。日本の大学機関はそういう立派な設備を持っていながら、なぜC++のような実用的な言語を教育できる人間がいないのか。理解に苦しむ。聞けば、京大では初年度にSICPをやり、二年目にC言語をやるのだそうだ。C言語! ああ、C++はC言語を改良し、なおかつC言語と同じシステムプログラミングを提供できるように設計されてきたというのに。

そして、さらにひどいことに、京大ではJavaのような一個の民間企業に独占された不自由で使いにくい言語を教育しているという。これはありえないことだ。C++にはそのような独占がないからこそ、安心して使えるのだ。しかも、Javaはその機能からして明後日の方向に向かっている。単にアルゴリズムやデータ構造を記述するために書きやすく、しかも実用的な言語というのであれば、今は便利な言語も多いというのに、なぜあのようなクソみたいな設計のJavaを選んでしまうのか。背景には、即戦力になる安い組み込みプログラマーを量産したいという業界の思惑があるらしい。情けないことだ。

はてなのセミナールームは、すこし条件が厳しい。プロジェクター、電源、無線LANこそ提供されているものの、椅子だけ並べて収容人数が40人(一応、机もあり、さる有名なCプリプロセッサーメタプログラマーは空気を読まずに使っていたが)、それも、土日はだめで平日の夜のみという、難しい条件だ。

平日の夜というのは、多くの職業プログラマーの参加を難しくしてしまう。それに、午後7時から始まる都合上、使える時間がせいぜい二時間ぐらいと短いので、そう何人も発表できない。

ただし、はてなのセミナールームには、この悪条件を吹き飛ばす、ある特別な設備が備わっている。Ustream配信のための設備だ。なんと、はてなは当日の勉強会をUstreamで配信してくれるという。

USTREAM: hatenatech

Ustreamとは、動画配信のためのプラットフォームで、閲覧者に不自由なFlash Playerを要求する邪悪なSaaSSである。そのため、一般的に言って、読者はUstreamを使うべきではない。

しかし、勉強会というのは所詮、物理的な場所で開催しなければならないわけで、場所をどこにしようとも、遠方であるために参加できない人間が出てくるものだ。開催日時を土日にしたところで、やはり物理的に己の肉体をその場所に持っていく都合のつかない人はいる。Ustreamのような閲覧に不自由ソフトウェアを要求するSaaSSは、紛れもなく悪であるが、この場合、もたらす善もゼロではないのではないか。

悩んだ挙句、今回は、はてなのセミナールームを借りて勉強会を行うことにした。

そして、講演者は、私ともう一人、コンパイル時プログラミングの権威、ボレロ村上に依頼した。当日の勉強会の動向は、近いうちに、日記として公開する。

将来的には、自分でカメラを用意して録画し、自由な動画、音声、コンテナーフォーマットで公開するべきだろう。ただし、そのためには私以外の撮影者が必要だ。それに、今回は初めて自分で主催する勉強会なので、そこまで手を広げることもできない。まず何としても、勉強会を計画し、場所の手配をし、告知して人を集め、発表して無難に終えるという、一連の仕事をこなさなければならないのだ。

少なくとも今回、積極的に新しいことをやり始めた結果、色々と可能性が広がってきた。京大の教室を借りての勉強会も、来年に行うよう調整中だ。現在の予定では、来年の春休み、つまり2月末から3月にかけての休日の昼間に、京大の教室を借りて勉強会を行うよう、調整中だ。内容は、今回のようにC++14の新機能でもいいし、あるいはなにか別のものでもいい。

さて、今回初めて、勉強会を主催した経験からいうと、勉強会を個人の力で開くのは色々と難しい。勉強会は最近の流行だが、実際に開催しようとすると、普通の営利活動では、到底正当化できないほどの費用と手間がかかる。私が今後もC++の啓蒙活動を続けるためには、どういう形であれ、私に金が入らなければならない。結局、私は霞を食べて深山に修行するわけにはいかないのだ。しかし、勉強会は、営利目的としてはいかにも無理だ。

やはり、さらなる劇的な変化が必要なのだろう。

2013-12-16

江添とボレロ村上の京都C++勉強会のスライド資料

今日の勉強会の、ボレロ村上さんの発表に使う資料が公開された。

すごい constexpr たのしくレイトレ!

江添によるスライド資料

C++14の新機能

まだ少し人数に余裕があるので、早いうちに参加申し込みをすれば、まだ間に合う。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-12-15

xkcd: gitコミット

xkcd: Git Commit

  • メインループ作成&タイミング処理
  • 設定ファイルのパース有効化
  • 細かいバグ修正
  • コード追加/編集
  • もっとコード
  • それ、コード
  • ああああああああ
  • くぁwせdrftgyふじこlp;
  • なにか適当に入力
  • 手ーーーーーーー

プロジェクトが進むにつれて、俺のgitコミットメッセージが適当になっていく。

さもありなん。

xkcd What if?: 液体の水銀や臭素やガリウムやタングステンや窒素やヘリウムの上でボートをこぐとどうなるの?っと

エクストリーム・ボート

水銀の湖の上でボートをこぐとどうなるの? 臭素は? 液体ガリウムは? 液体タングステンは 液体窒素は? 液体ヘリウムは?

–Nicholas Aron

一つづつみていくことにしよう。

臭素と水銀は、室温で液体になる唯一の純粋な元素だ。

水銀の海の上でボートをこぐのは、おそらく可能だ。

水銀はとても密度が高いので、鋼鉄球すら水面に浮かぶほどだ。

ボートは浮きすぎて、水銀にあまり沈まないかも知れないので、パドルに体重をかけなければ水面下に棹させないかもしれない。

結論としては、ちょっと難しいかも知れないし、あまり早く焦げないかも知れないが、おそらく水銀上でボートをこぐのは可能だろう。

読者は水かけ合戦をしないほうがよい。

臭素は水とほぼ同じ密度を持っている。そのため、標準的な手こぎボートは、理論的には、浮かぶはずだ。

ただし、臭素は悲惨だ。まず第一に、臭いがひどい。臭素(bromine)という名前は、古代ギリシャ語の"brōmos"から来ていて、意味は「臭う」だ。それだけではなく、臭素は、多くの物質と激しく反応する。読者はアルミニウム製のボートを使うのはやめておいたほうがよい。

これでもまだやめる気にならないのであれば、臭素の物質安全データシートには以下の文面があることを記しておこう。

  • 深刻な火傷及びに潰瘍
  • 消化器官の穿孔
  • 永続的な角膜混濁
  • 空間識失調、不安感、失望感、筋肉協調運動不能、情緒不安定
  • 血を伴う下痢

読者は臭素の湖で水かけ合戦をしないほうがよい。

液体ガリウムは不思議な物質だ。ガリウムはバターのように、室温の少し上の温度で溶ける。手のひらの上で長時間保持することはできない。

それなりの密度はあるが、水銀ほどの密度はないので、ボートをこぐのは水銀よりは簡単だろう。

ただし、これも、アルミニウム製のボートはやめておいたほうが良い。なぜならば、アルミニウムは、その他の多くの金属と同じく、あたかもスポンジが水を吸い込むように、ガリウムを吸収してしまうからだ。ガリウムはアルミニウムの中に急激に広がり、その化学的特性を変えてしまう。変化したアルミニウムは、とても脆く、湿った紙のようにちぎることができる

水銀とガリウムに共通の性質で、アルミニウムを破壊してしまうのだ。

「ガリウムの湖でアルミニウムのボートを漕ぎだしちゃいけないよ」とは、筆者の婆ちゃんがよく言っていたことだ(筆者の祖母はすこし変わっていたのだ)

液体タングステンは難しい。

タングステンはどの元素よりも融点が高い。これはつまり、我々はその特性について、あまりよく知らないということである。特性を検証できない理由は、すこし馬鹿げたように思えるかも知れないが、液体タングステンを保持できる容器がないためである。並大抵の容器では、タングステンが溶けるより先に、容器を構成する物質が溶けてしまう。炭化タンタルハフニウムのようなごく一部の化合物のみが、わずかに高い融点を持つだけだ。ただ、そのような化合物で液体タングステン用の容器を作成できた者はいない。

液体タングステンがどのくらい熱いのかということを実感させるために、その具体的な融点の温度(3422℃)を書くということもできるが、以下のように説明したほうがわかりやすいだろう。

液体タングステンはあまりにも熱いため。もし溶岩に滴下したならば、溶岩はタングステンを凍らせてしまうのだ。

言うまでもなく、もし読者が液体タングステンの海にボートで漕ぎだしたならば、読者とボートは両方共、瞬時に発火炎上するだろう。

液体窒素はとても冷たい。

液体ヘリウムはさらに冷たいが、どちらも絶対零度に近く、南極の最低温度よりも下だ。そのため、ボートで漕ぎだす目的のためには、温度の違いは瑣末なものだ、。

液体窒素の安全性に関するDartmouth工業ページには、以下の文面が並ぶ

  • 有機物と激しく反応
  • 爆発する
  • 室内の酸素を減らす
  • 激しい着衣の炎上
  • 前兆なしの窒息

液体窒素は、水に近い密度を持っている。そのため、手こぎボートは浮かぶだろう。ただし、読者は長時間生存できないだろう。

もし、実験開始時点で、窒素の上の空気が室温であったならば、急速に冷却され、読者とボートは、空気が凝縮された濃い霧に覆われて窒息するだろう。(これは液体窒素をそそいだ時に発生する湯気と同じ効果である)。凝縮は凍結を引き起こし、読者をボートを急速に雪に埋もれさせるだろう。

暖かい空気は、窒素の表面を蒸発させる。これは湖面の酸素を減少させ、読者は窒息するだろう。

もし、空気(あるいは窒素)が、蒸発を防ぐほど十分に冷たいのであれば、読者は低体温症により、死亡するだろう。

液体ヘリウムはさらにひどい。

まず、液体ヘリウムは水の8分の1しか密度がないため、自重を支えるために、読者のボートは8倍の大きさを有していなければならない。

「俺らにはでっかい船が必要だ」
「まあでも、サメは問題にならんよな」

ただ、ヘリウムは厄介だ。もし、2度ケルビン以下に冷却された場合、超流動になる。これには不思議な特性がある。毛細管現象により、容器の壁を登り上がるのだ。

約秒速20cmほどで登るので、30秒以内に、ボートの底に液体ヘリウムがたまり始める。

液体窒素の時と同じく、低体温症により急速な死をもたらす。

ひとつ慰めになるとすれば、横たわって死につつある中、読者はとても奇妙な現象を観察することになるだろう。

読者の体を急速に覆いつつある超流動のヘリウムの層は、ほとんどの物質と同じく、音波を伝える。しかし、液体ヘリウムには全く別の形の波、ヘリウムの層をゆっくり伝わる波があるのだ。これは超流動でしか観測されていないもので、不思議で詩的な、第三の音という名前が与えられている。

読者の鼓膜はもはや機能しておらず、そもそもこの種類の振動を検出することはできないだろうが、巨大なボートの床の上で凍てついて死につつある読者の耳には、人間が未だかつて聞いたことのない、第三の音で満たされていることであろう。

これは、少なくとも、とってもクールだ。

C++03とC++14の違い: ライブラリ導入編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

今回は、ライブラリ導入編だ。ライブラリ導入(Library Introduction)とは、C++の標準ライブラリを使うにあたっての約束事を定める章である。たとえば、予約されている名前なども、ここで定められている。

新しい予約された識別子

C++11/14では、新しい標準ライブラリのために、多くの識別子を導入した。既存のC++03のコードで、たまたまその識別子を使っているコードは、名前の衝突を起こす可能性がある。

とはいえ、識別子はほとんどstd名前空間スコープの下にあるし、マクロ名もきぞんのコードと衝突を起こさないように注意深く命名されているので、通常は問題になることはない。

新しいヘッダー

C++11/14では、多くの新しいヘッダーが追加された。

C++の新しくつかされたヘッダーは以下の通り。

<array>, <atomic>, <chrono>, <codecvt>, <condition_variable>, <forward_list>, <future>, <initializer_list>, <mutex>, <random>, <ratio>, <regex>, <scoped_allocator>, <system_error>, <thread>, <tuple>, <typeindex>, <type_traits>, <unordered_map>, <unordered_set>

また、最新のC言語規格に合わせて、以下のヘッダーが追加された。

<ccomplex>, <cfenv>, <cinttypes>, <cstdalign>, <cstdbool>, <cstdint>, <ctgmath>, <cuchar>.

たまたま、同じ名前のヘッダーを使っていた場合、問題になるだろう。しかし、ヘッダーの名前も注意深く選ばれているので、通常は衝突することはないだろう。

std::swapのヘッダーが<algorithm>から<utility>に変更

std::swapを使うコードは、C++11からはutilityを#includeしなければならない。

予約された名前空間posixの追加

posixという名前の名前空間が、あらたに追加された。これは、現時点では空っぽだが、将来使うために予約されている。

もし、posixという名前の名前空間をC++03のコードで使っていた場合、互換性の問題がある。

マクロ名として名前キーワードの追加

attribute tokenとして使われている、override, final, carries_dependency, noreturnは、マクロ名として使うことができない。

もし、このような名前のマクロ名を使っている場合は、互換性の問題がある。

そもそも、まともなC++プログラマーはCプリプロセッサーマクロを使うべきではない。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

また、私の書いたC++11のコア言語を完全に解説した参考書もある。

Gumroadで購入: C++11参考書:C++11の文法と機能

今すぐ閲覧: C++11: Syntax and Feature

誤りがあればGitHubでPull Requestせよ: https://github.com/EzoeRyou/cpp-book

この参考書は、C++の規格のみを参照して記述しており、特定のC++の実装(コンパイラー)で確かめただけで合法、違法を判断する、世間一般によくある駄本とは根本的に質が異なる本である。本書に誤りがあるとすれば、

  1. 誤字脱字
  2. 筆者の規格文面の解釈間違い
  3. 規格文面の誤り

だけである。まだ、世の中の安定版コンパイラーはC++11の規格をバグフリーで完全に実装していない。

2013-12-14

SteamOSが公開された。

SteamOS FAQ :: Steam Universe

[Phoronix] SteamOS 1.0 Is Based Upon Debian Wheezy

[Phoronix] SteamOS Has Its Own Graphics Compositor

[Phoronix] SteamOS Compositor Details, Kernel Patches, Screenshots

[Phoronix] Former NVIDIA, Microsoft Developers Doing Lots Of The SteamOS Work

Valveの忌まわしきDRM付きの邪悪なゲームソフトウェア流通プラットフォームであるSteamに特化したGNU/Linuxのディストロ、SteamOSが公開された。

この不自由ソフトウェアの実行をたやすくしたSteamOSは、Debian Wheezyがベースとなっている。Debianを選んだ理由は、Valveがカスタマイズするものとしては、UbuntuよりDebianの方がやりやすいからだという。

nVidiaやAMDの最新版の不自由なグラフィックドライバーや、最新版のMesaがbackportされているという。また、LinuxカーネルもWheezyの3.2ではなく、3.10となっている。

SteamOSは、デフォルトのUIがBig Pictureモードとなっている。これは、Steamで遊ぶことに特化したUIだ。このBig Pictureモード自体は、GNOME上に構築されている。設定で有効にすれば、デスクトップに切り替えることもでき、普通のGNU/Linuxデスクトップ環境としても使えるそうだ。ただし、初期ではrootアカウントにパスワードがかけられておらず、デスクトップを有効にする際に、パスワードを設定する必要があるのだという。

ValveのFAQでは、passwordコマンドを使えとのことで、まだまだベータといった感じが漂う。

SteamOSは独自のグラフィックコンポジターを使っているという。独自というべきなのか、ややマイナーというべきなのか。その名前をXcompmgrといい、X11上で動作する。Xcompmagr自体は、Keith Packardが書いた、結構昔のコンポジターだ。とても軽いことが特徴で、利用者もいることはいるそうだ。最近は活動的ではなかったそうなのだが、いったいどういうことなのだろう。まあ、今すぐにゲームを実行する必要のある関係上、WaylandやMirのような、全く新しい実装という冒険はできなかったということか。ちなみに、上流のXcompmgrと、SteamOSのXcompmgrのdiffは、2400行になるそうだ。

SteamOSのLinuxカーネルは、linux 3.10 - PREEMPT_RT_FULLで、かなり大量のパッチを当てている。特にリアルタイムカーネル関連のパッチが多いのだとか。

初期化には、SysVinitを使用。今流行りのsystemdではなければ、UbuntuのUpstartでもない。ここも保守的だ。

AMD用のプロプライエタリなバイナリブロブのドライバーも入っているものの、現在のところ、nVidiaのGPUを推奨しているのだとか。

リアルタイムカーネル、X11のグラフィックコンポジターで軽量に定評のあるXcompmgr、SysVinit、ゲーム用の固定ライブラリバイナリセット、だいぶ保守的でゲームの高速動作に特化したような思想が伺える。

私は使いたいとは思わないが、こんな制限的なシステムでも、もたらす善の方が大きいのだろうか。おぼつかなし。

2013-12-13

ECMAがDartを標準化すべく技術委員会を立ち上げた

[Phoronix] ECMA Is Working On Standardizing Google's Dart

ECMAがDartを標準化すべく技術委員会を立ち上げたそうだ。

Dartについては色々と期待している。何しろ、初期に公開した規格書が、まともにフォーマルな文面を用いていて、実に素晴らしかったからだ。

最近のDartの動向は追いかけていないが、なかなか面白そうではある。

ただし、それはDartの独立した実装が複数出てきてからの話だ。現状で、Googleの独壇場なのは危険だ。

C++03とC++11の違い: テンプレート編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

今回は、テンプレートについて、C++03とC++11/14の違いを取り上げる。

C++11では、export機能が廃止となった。

exportは、実装例が極めて少なかったために、C++11では廃止となった。

この変更による互換性の問題は、ほとんどないだろう。というのも、export機能自体が使われていなかったのだから。

C++11では、入れ子となったテンプレートの連続したアングルブラケットの間に、空白文字を挟む必要がなくなった。

template < typename T >
struct S { } ;

// C++03では違法
// C++11では合法
S<S<int>>> s ;

C++03では、右シフト演算子、operator >>と文法上曖昧になるため、必ず空白文字を挟まなければならなかったのだ。

// 空白文字が必要
S<S<int>> > s ;

このような些細な文法上の問題は、利用者の混乱を防ぐために、コンパイラーの努力で何とかするべきだという意見により、C++11では、このような場合、演算子ではなくテンプレートのアングルブラケットだと解釈するようになった。

この変更により、C++03では、右シフト演算子と解釈されるために合法だったコードの解釈が変わってしまう。

template <class T> struct X { };
template <int N> struct Y { };

// C++03では合法、1 >> 2は右シフト式
// C++11では違法、文法上の誤り。
X< Y< 1 >> 2 > > x;

ただし、このようなコードは稀であろうから、おそらくは大丈夫だろう。

C++11では、内部リンケージを持つ関数を依存呼び出しできるようになった。

C++03では、非修飾名での依存呼び出しの際には、外部リンケージの関数しか考慮されなかった。内部リンケージの関数はオーバーロード解決に置いて考慮されなかった。そのため、以下のようなコードは、厳格に規格準拠のC++03の実装とC++11の実装で実行した場合、挙動が異なる。

void f( long ) { } // #1
static void f( int ) { } // #2


template < typename T >
void g( T x )
{
    // C++03では#1を呼ぶ
    // C++11では#2を呼ぶ
    f( x ) ;
}

int main()
{
    g( 0 ) ;
}

C++03では、外部リンケージの関数しか考慮されないので、#2が呼ばれることはない。C++11では、単に実装の簡単化のため、内部リンケージも考慮されることになったので、#2が呼ばれる。

このこととは直接関係ないが、依存呼び出しにおいては、プログラムの全翻訳単位の、その文脈で発見できない名前も含めたすべての外部リンケージを持つオーバーロード関数の候補で、もし、オーバーロード解決の結果、より最適な候補となる関数が存在した場合は、プログラムは違法となる。

例えば、unit_1.cpp, unit_2.cppという、2つのソースファイル、2つの翻訳単位からなるプログラムがあったとする。

// unit_1.cpp
void f( int ) { } // #1
// unit_2.cpp
void f( long ) { } // #2

template < typename T >
void g( T x )
{
    f( x ) ; // 依存呼び出し
}

int main()
{
    g( 0 ) ; // 違法
}

このコードは違法である。なぜならば、依存呼び出しで#2が最適関数となるが、別の翻訳単位で、名前は見つからないものの、より最適な関数があるために、プログラムは違法となる。

これは、テンプレートの特殊化が翻訳単位ごとに異なる結果となることを防ぐためである。

依存名というのは厄介だ。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

また、私の書いたC++11のコア言語を完全に解説した参考書もある。

Gumroadで購入: C++11参考書:C++11の文法と機能

今すぐ閲覧: C++11: Syntax and Feature

誤りがあればGitHubでPull Requestせよ: https://github.com/EzoeRyou/cpp-book

この参考書は、C++の規格のみを参照して記述しており、特定のC++の実装(コンパイラー)で確かめただけで合法、違法を判断する、世間一般によくある駄本とは根本的に質が異なる本である。本書に誤りがあるとすれば、

  1. 誤字脱字
  2. 筆者の規格文面の解釈間違い
  3. 規格文面の誤り

だけである。まだ、世の中の安定版コンパイラーはC++11の規格をバグフリーで完全に実装していない。

JavaScriptへVimを移植

Vim.js - JavaScript port of Vim

なんと、JavaScriptへVimを移植したのだそうだ。準備に時間がかかり、さらに反応も悪いが、たしかにこれはVimだ。いや、Vimそのものだ。

Hacker Newsでは、さっそく、Atwordの法則を引用するものがいる。Atwordの法則、「JavaScriptで書かれ得るプログラムは、いずれJavaScriptで書かれる。」

この法則は、Tim Berners-Leeの the Principle of Least Powerをもとにしている。Tim Berners-Leeは、WebでJavaScriptのような貧弱なプログラミング言語が使われていることを大変喜んでいる。なぜならば、JavaScriptは比較的簡単に解釈できるからだ。そのため、データやプログラムは、他人にも比較的簡単に処理できる。これがもし、Javaアプレットとか、Flashなどで書かれていたならば、なるほど、確かに見た目はいいかもしれないが、とても他人にとって使いづらいデータになってしまう。

Design Issues for the World Wide Web

歯の詰め物がとれた

自宅で遅めの昼食を認めていたところ、右下の歯の詰め物が取れてしまった。

思えば、ここは確か人生初に虫歯になって歯医者にかかったところだ。たしか、7,8年前だったと記憶している。保険の範囲内の治療で、7,8年持てば、まあ平均的といったところだろうか。

どうせこの箇所は、ここ数ヶ月、水を飲んだり、冷たいサラダを食べたりしただけで、わずかに痛むようになっていたので、そろそろ歯医者に行って、診てもらわなければならないと思っていたところなのだ。ただ、その痛むというのが、食べ始めのほんの数秒痛むだけで、痛み自体も僅かなものなので、ついつい放っておいてしまっていた。

しかし、冷たいものが痛むとか、食事で詰め物が取れたということは、中で虫歯にでもなっているのかもしれない。鏡でみてもわからないので、やはり歯医者に行かなければならない。

しかし、残念ながら、今日はあいにくと普段行っている歯医者が開いていない。幸い、土曜日もやっている歯医者なので、明日行くことにしよう。

追記:幸い、とれた詰め物は無事だったので、付け直すだけですんだ。

C++03とC++11の違い: 特別なメンバー関数編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

今回は、特別なメンバー関数について解説する。

C++11では、デフォルトの実装が違法になる暗黙に宣言される特別なメンバー関数は、delete定義される。

delete定義はC++11からの機能だ。これにより、宣言は参照するが、定義を使わないために問題にならなかったC++03のコードが、C++11では明確に違法になる。

いまいちいいコード例が思い浮かばない。

C++11では、デストラクターが暗黙で無例外指定になった。

これにより、デストラクターから例外で脱出すると、std::terminateが呼ばれる。

struct S
{
    // call std::terminate
    ~S() { throw 0 ; } 
} ;

これは、デストラクターは例外を投げるべきではないという原則による変更である。もし、C++11で、どうしてもデストラクターから例外を投げたい場合は、noexcept(false)を明示的に使わなければならない。

struct S
{
    // OK
    ~S() noexcept(false)
    { throw 0 ; }
} ;

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

また、私の書いたC++11のコア言語を完全に解説した参考書もある。

Gumroadで購入: C++11参考書:C++11の文法と機能

今すぐ閲覧: C++11: Syntax and Feature

誤りがあればGitHubでPull Requestせよ: https://github.com/EzoeRyou/cpp-book

この参考書は、C++の規格のみを参照して記述しており、特定のC++の実装(コンパイラー)で確かめただけで合法、違法を判断する、世間一般によくある駄本とは根本的に質が異なる本である。本書に誤りがあるとすれば、

  1. 誤字脱字
  2. 筆者の規格文面の解釈間違い
  3. 規格文面の誤り

だけである。まだ、世の中の安定版コンパイラーはC++11の規格をバグフリーで完全に実装していない。

2013-12-12

Vimにclang_completeを導入した

NoeBundleを得て、Vimのプラグイン導入を恐れなくなった私は、さっそく、Vimにclang_completeを導入した。

Rip-Rip/clang_complete

NeoBundleを使った。とりあえず色々と試した結果、、以下の設定に落ち着いた。

" Install clang_complete
NeoBundle 'Rip-Rip/clang_complete'

let g:clang_periodic_quickfix = 1
let g:clang_complete_copen = 1
let g:clang_use_library = 1

" this need to be updated on llvm update
let g:clang_library_path = '/usr/lib/llvm-3.4/lib'
" specify compiler options
let g:clang_user_options = '-std=c++11 -stdlib=libc++'

他にもテンプレートや関数の引数まで保管してくれるスニペットや、最長一致のものを自動的に入力してくれるオプションもあるのだが、私はテキストエディターが勝手に文字列を入力するのが嫌いなので、有効にはしなかった。

さて、この結果として、私のVim環境は最強のC++IDE環境になってしまった。今や私のVimは、以下のことができる。

  • Makefileを使ってC++11までのコンパイルや実行ができる
  • clang_completeを使ってC++11までの補完ができる
  • Wandboxを使ってC++14のオンラインコンパイルができる

ああ、なんということだ。Windows環境を離れて、唯一心残りのあった、Visual StudioによるInteliSense以上のものが、今ここにある。しかも、もはやMSのような不自由ソフトウェアの追随を許さないほどの高機能だ。しかも、全て自由ソフトウェアだけで実現できている(ただしWandboxは私が支配力を持たないSaaSSであるが)。いや、不自由ソフトウェアでは実現できないことだ。ああ、C++といえばWindowsという時代(一時期MSVCの方がテンプレートのサポートが優れていた時代があった)は、本当に終わってしまった。

ああ、はやくClang 3.4とGCC 4.9が安定リリースされ、C++14が正式発行されて、C++14の補完とローカルでのコンパイルができるようになりたい。

C++03とC++11の違い: 宣言子編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

今回は、宣言子だ。

C++11にはリスト初期化のNarrowing Conversionが禁止された。

以下のような合法なC++03コードが、C++11では違法となる。

// C++03では合法
// C++11では違法
int a[] = { 1.0 } ;

C++11では、リスト初期化というものを新たに導入し、従来aggregateにのみ許されていた{ }による初期化を、ユーザー定義型のクラスにももたらした。この心機能の追加にあたって、リスト初期化では、浮動小数点数から整数型や、より表現できる範囲が狭い可能性のある型への暗黙の変換(例:doubleからfloat、intからshort)を、縮小変換(narrowing conversion)と名付け、明確に禁止した。

もし、どうしても型変換を行いたい場合は、明示的なキャストが必要になる。

// well-formed
int a[] = { static_cast<int>( 1.0 ) } l

そもそも、このような暗黙の型変換には頼ってはならないのである。強い静的型付けによって、コンパイル時にくだらない不具合を発見できるべきで、暗黙の型変換はその妨げになる。

いつか、暗黙の型変換が一切廃止される日をこの目で見たい。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

また、私の書いたC++11のコア言語を完全に解説した参考書もある。

Gumroadで購入: C++11参考書:C++11の文法と機能

今すぐ閲覧: C++11: Syntax and Feature

誤りがあればGitHubでPull Requestせよ: https://github.com/EzoeRyou/cpp-book

この参考書は、C++の規格のみを参照して記述しており、特定のC++の実装(コンパイラー)で確かめただけで合法、違法を判断する、世間一般によくある駄本とは根本的に質が異なる本である。本書に誤りがあるとすれば、

  1. 誤字脱字
  2. 筆者の規格文面の解釈間違い
  3. 規格文面の誤り

だけである。まだ、世の中の安定版コンパイラーはC++11の規格をバグフリーで完全に実装していない。

2013-12-11

C++で、(a/b)*b + a%b != aとなる例

C++では、整数a, bにおいて、"(a/b)*b + a%b"の結果が、"a"と等しくない場合、a/bとa%bの挙動は未定義である(5.6 paragraph 4)

この条件に当てはまるaとbの値が、さっぱり思いつかなかった。b = 0の場合はそうなのだが、それは一つ前のセンテンスでカバーされている。わざわざ書く以上、b = 0以外の例があるはずだ。そこで人に聞いた。一瞬で答えを教えてもらった。

aとbがint型で、int型は2の補数で表現されていて、INT_MIN == -2^(n-1) (nはintのビット数)の場合における、a = INT_MIN, b = -1

なるほど、2の補数だから、最小値と最大値の絶対値が1ずれるわけだ。ずれは最小値の絶対値の方が1大きくなる。-1で割るということは、つまり最大値が最小値の絶対値になるということで、オーバーフローする。

#include <limits>
#include <iostream>

int main()
{
    int a = std::numeric_limits<int>::min() ;
    int b = -1 ;

    int c = (a/b)*b + a%b ;

    std::cout << c << '\n' ; 
}

興味深いことに、GNU/Linux x64のGCCとClangでコンパイルすると、標準出力にFloating point exceptionと出力され、その時点でプログラムの実行が止まる。

xkcd What if?: 星の王子様に出てきた小さな惑星が本当にあったらどうなるの?っと

またもやxkcdから。

小さなお星様

もし、小惑星がとても小さく、しかし超密度であれば、星の王子様みたいに生活できるの?っと

Samantha Harper

先週、我々は巨大な惑星における生活を考察した。今週は、小さな惑星に目を向けよう。

アントワーヌ・ド・サン=テグジュペリ著の星の王子様は、遠く離れた小惑星からの旅人のお話だ。読みやすく、どこか物悲しく、印象深い絵本だ。[1]。子供向けの本だが、対象読者を限定するのは難しい。ともかく、大衆受けしていて、歴史的にもベストセラーになっている。

[1]: 星の王子様のような話をもっと読みたければ、Mallory Ortberg著のこの素晴らしい小説を下までスクロールするといい。

星の王子様は1942年に書かれた。これは小惑星について書くにあたって、とても興味深い年代である。というのも、1942年には、我々はまだ、小惑星がどのような形をしているか知らなかったのだ。当時の最高の望遠鏡を使っても、最大の小惑星は、単なる光の点としてしか観測できなかった。実は、asteroidという名前の由来はそこから来ている。意味は「星のような」だ。

我々が小惑星の形について初めて確認できたのは、1971年、Mariner 9が火星に到達して、フォボスとダイモスの写真を撮影した時だ[2]。この、当時小惑星と信じられていた月[3]は、現代風のポテトのような形の小惑星のイメージを形成した。

[2]: コレがフォボスの画像だ。典型的な小惑星の見た目をしている。この計画に画像アーカイブは、NASA Space Science Data Centerにあるが、奇妙なことに、NSSDCは、実際の画像閲覧は、どっかの個人サイトTripod pageに丸投げしている。

[3]: 興味深いことに、フォボスとダイモスは小惑星の形をしているが、最近の研究によれば、小惑星ではないという。Craddock, Robert AのAre Phobos And Deimos The Result Of A Giant Impact? Icarus (2010)を参照。

1970年代以前、SFでは小さな小惑星も、惑星のように丸いものであるとの考えが一般的だった[4]。

[4]: 皆がそういう考えだったわけではない。だいぶ正確な考えの人もたくさんいた。ヘンテコな考えもあった。

星の王子様はこの考えをさらに飛躍させた。小惑星が、小さな惑星で、重力があり、空気があり、バラもある。ここで科学的に糾弾するのはあたらない。なぜならば、(1) これは小惑星の話ではないし、(2) 大人が物事を真面目に考えすぎることを茶化すためのものだからだ。

そこで、お話を変更するのではなく、科学的に考えればどうなるのかについてみてみよう。もし、歩き回れるほどの表面重力を持った超密度の小惑星があるとする。その小惑星は、とても面白い特性を持っている。

もし、小惑星が半径1.75メートルであれば、地表で地球と同等の重力を有するためには、その質量は500万トンなければならない。これは、地球上に存在するすべての人間分の質量と同じ程度の質量だ。

地面に立つと、潮汐力を感じるだろう。頭より足のほうが重く感じるので、ゆっくりとストレッチしたような感覚を覚えるだろう。あたかも、丸まったゴムボールの上でストレッチしているような感じ、あるいは、頭を中央に向けてメリーゴーラウンドに寝そべったような感覚だ。

地表における脱出速度は、秒速5メートルだ。これは全力疾走よりは遅いが、それでもそれなりには速い。目安として、もし読者がバスケットボールをダンクシュートできなければ、垂直跳びで脱出するのは無理だ。

しかし、脱出速度の面白いところは、進む方向は関係がないということだ[5]。もし、読者が脱出速度よりも速く動けば、その方向が惑星に向かうものでないかぎり、脱出できる。つまり、小惑星を水平方向に走って、崖でジャンプしてもオサラバできるのだ。

[5]: ・・・だからこそ、脱出速度(escape velocity)は、本当は脱出速度(escape speed)と呼ばれるべきなのだ。方向がないというのは(それこそがspeedとvelocityを区別するものなのだから)、とても重要な違いだ。

もし、読者が惑星を脱出するほど速く動けなかったとしたら、軌道上を回ることになる。読者の軌道速度は約秒速3メートルだ。これはジョギングの速度である。

だが、これはとても奇妙な軌道になるだろう。

潮汐力が読者の複数箇所に対して働くことになる。もし、読者が惑星方向に腕を伸ばしたとすると、その腕は体の他の部分よりより強く引かれることになる。もし、腕を地面に下ろしたとすると、体の他の部分は上方向に押し上げられる。これはつまり、読者の体の他の部分は、重力をより軽く感じることになる。結果的に、体の各部位が、それぞれ別々の軌道を辿ろうとするのだ。

このような潮汐力下における巨大な軌道物体は--例えば、月--は、一般的に、粉々に砕けて輪を形成する。これは読者には起こらない。しかし、軌道はカオス的かつ不安定なものとなるだろう。

このような軌道については、Radu D. RugescuとDaniele Mortariによる興味深い論文[6]で検証されている。彼らのシミュレーションによれば、巨大な長い物体は、中心部を軸に不思議なパターンをたどるのだという。質量の中心点すら、古典的な円を描かない。五角形軌道のこともあれば、カオス的に回転した挙句、惑星に衝突するものもある。

[6]: >Rugescu, Radu D., Mortari, Daniele "Ultra Long Orbital Tethers Behave Highly Non-Keplerian and Unstable" WSEAS Transactions on Mathematics, Vol. 7, No. 3, March 2008, pp. 87-94.

このような解析には、実は実用的な応用対象がある。長年、とても高い、車輪とヒモで、荷台を重力圏内外に運ぼうという提案がなされている。いわば空中に浮かぶ 宇宙エレベーターだ。そのようなヒモは、荷台を地表と月間で移動させることができたり、地球の大気圏内から宇宙船を捕まえたりできる。軌道ヒモの不安定性は、この計画における難しい課題となっている。

さて、この超高密度小惑星の住人は、とても注意深く暮らさなければならないだろう。もし速く走り過ぎると、激しく揺さぶられて、昼飯を戻してしまう深刻な危険がある。

幸い、垂直跳びは問題ない。

星の王子様の生活は大変そうだ。

C++03とC++11の違い: 式編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

今回は式(expression)について。

C++11では、整数の除算と剰余の丸め方向がゼロに向かう。

これはC99との互換性を向上させるための変更である。

C++03では、 整数a, bに対して、a / b の結果が、実数では0.9とか-0.9になった場合、整数の結果の丸め方向がどちらになるのか規定されていなかった。

9 / 10 ; // 0? 1?
-9 / 10 ; // 0? -1?

C++03では、整数a, bで、a, bが、片方、あるいは両方とも正の整数でない場合、a % bの符号は実装依存だった。

3 % 2 ; // 1
-3 % 2 ; // 1? -1?
3 % -2 ; // 1? -1?
-3 % -2 ; // 1? -1?

C++03では、C言語の規格策定で、ISO Fortran 90、つまりISO/IEC 1539:1991の仕様に合わせるのが推奨されていると注記している。

Fortran 90規格の文面によれば、除算の商は、必ずゼロ方向に丸められる。

 9 / 10 ; // 0
-9 / 10 ; // 0

剰余の符号は、以下のようになる。

 8 %  5 ;    //  3
-8 %  5 ;    // -3
 8 % -5 ;    //  3
-8 % -5 ;    // -3

C99はFortranに合わせるによう規定され、C++11でも、C99との互換性向上のため、この規定に合わせることにした。

それにしてもわからないのが、未定義動作となる条件だ。a / bの商が式の結果の型で表現可能ではない場合というのはいいとしても、(a/b)*b + a%bがaと等しくない場合というのは、どうやったら可能になるのかわからない。そういうハードウェアがあるのだろうか。

参考文献:GFortranStandards - GCC Wiki

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

2013-12-10

xkcd What if: お茶をどのくらい激しくかき混ぜたら沸騰するの?っと

xkcdのWhat ifで、お茶をどのくらい激しくかき混ぜたら沸騰するのかということについて考察していた。

What if: 紅茶をかき混ぜる

ぼんやりと熱い紅茶をかき混ぜながら、こう思った。「まてよ、俺は運動エネルギーをこのカップに与えているのではないか?」とね。お茶をかき混ぜると冷めやすくなるけど、もし、高速にかき混ぜたらどうだろうか。かき混ぜることによって、お湯を沸かすことができるだろうか。

Will Evans

ノー

基本的な考えとしては間違ってない。温度というのは単なる運動エネルギーだ。お茶をかき混ぜるということは、運動エネルギーを与えているということだ。そのエネルギーはどこかに行く。お茶がにわかに浮遊したり光を放ったりしない以上、そのエネルギーは熱に変わっているはずだ。

熱に気が付かない理由は、それほど多くの熱を与えていないからだ。水を熱するにはとても多くのエネルギーを必要とする。容量あたりで言えば、水は通常の物質の中では相当に多くの質量あたりの熱容量を持っている[1]

[1]: 水素とヘリウムは、より多くの質量あたりの熱容量を持っているが、これらは気体だ。通常の物質で水に勝るのは、跡はアンモニアぐらいしかない。これら3つの物質は、体積あたりで比較すれば、水に負ける。

水を室温から沸騰寸前まで二分で加熱したい場合、相当の力が必要になる。

\[1\text{ cup}\times\text{Water heat capacity}\times\tfrac{100^\circ\rm{C}-20^\circ\rm{C}}{2\text{ minutes}}=700\text{ watts}\]

注意:沸騰寸前の水を沸騰にまで持って行くには、沸騰寸前までにかかったエネルギーに加えて、さらに大量のエネルギーを必要とする。これはenthalpy of vaporizationと呼ばれている。

この数式によれば、二分でコップ1杯のお湯を得たければ、700ワットの力が必要になる。通常の電子レンジは、700から1100ワットぐらいで、お茶を淹れるぐらいにコップ1杯の水を熱するのに、二分ほどかかる。動くってのは素晴らしいことだ。[2]

[2]: もし動かないとしたら、「非効率」とか「熱源」とかに文句を言うべきだ。

700ワットを二分間というのは、とてつもなく大きなエネルギーだ。水がナイアガラの滝から落ちるとき、運動エネルギーを得て、落下地点で熱に変わる。しかし、相当な距離を落下しても、水は小数点以下の温度ぐらいしか上昇しない[3]。コップ1杯の水を沸騰させるには、大気圏外の高さから落下させなければならない。

[3]: \(\text{Height of Niagra Falls}\times\frac{\text{Acceleration of gravity}}{\text{Specific heat of water}}=0.12^\circ\text{C}\)

オチャアアアアアアァァァァァーーー!!!

かき混ぜることと電子レンジを比較すると?

工業ミキサーの技術レポート[4]によると、筆者の推定では、カップのお茶を激しくかき混ぜると、約百万分の一ワットの熱を与えることになる。これは無視できる範囲だ。[5]

[4]: Brawn Mixer, Inc., Principles of Fluid Mixing (2003)

[5]: お茶はこれよりはやく熱を失う。参照:Ben Harden, Tea temperature vs. Time graph

かき混ぜることによる物理的効果は、やや複雑だ[6]。ティーカップは、その上を対流する空気によって熱が奪われるため、上から冷めていく。かき混ぜるということは、新鮮な温かい水を底からもたらすので、冷却の過程に貢献するだろう。しかし、かき混ぜることによって、空気の流れが阻害され、コップを温めることもある。データ無しでは、なんとも言えない。

[6]: ある状況では、液体をかき混ぜると温度維持に貢献することになる。温かい水は上昇し、水の量が広く十分ならば(例えば海)、温かい層が水面に形成される。この温かい層は冷たい層よりも、ずっとはやく熱を放出する。かき混ぜることに寄って、この温かい層を崩すと、熱を失う速度が減少する。ハリケーンの移動が止まると、力を失うのは、このためである。ハリケーンの波が冷たい水をかき混ぜて、主要なエネルギー源である薄く温かい水の層から遠ざけるのだ。

幸い、我々にはインターネットがある。StackExchangeユーザー、drhodesが、かき混ぜるVSかき混ぜないVSスプーンを連続的に出し入れすることについて、ティーカップの冷却率を計測してくれたのだ。素晴らしいことに、drhodes君は高精度グラフもうpしてくれたし、さらになんと、生データまでうpってくれたのだ。どこぞの科学記事よりよほどデキる奴だ。

結論:かき混ぜるかどうか、スプーンを出し入れするかどうかでは、何も変わらない。お茶は同じ割合で冷却されていく(ただし、スプーンの出し入れはわずかに冷却速度が早かったが)

さて、もとの質問に戻ろう。十分に激しくかき混ぜたら、お茶を沸騰させることができるか?

ノー

まず問題なのだ力だ。700ワットとは、約1馬力にあたる。そこで、お茶を二分間で沸騰させたければ、少なくとも馬を一頭用意して、十分に激しくかき混ぜてもらわなければならない。

あの・・・君、もしよかったら、その・・・
スプーンをくわえて、かき混ぜてもらえるかな?

お茶を長時間加熱することにより、必要な力を減少させることはできる。しかし、時間をかけ過ぎると、加熱より冷却速度が勝ってしまう。

仮にスプーンを十分に激しく--毎秒一万回--かき混ぜることができたとしても、液体力学が立ちはだかる。これほど高速になると、お茶にはキャビテーションが発生する。スプーンの軌跡に真空が発生し、かき混ぜ効率を下げてしまうのだ。

それに、お茶にキャビテーションが発生するほど十分に激しくかき混ぜた場合、水面部分は激しく上昇し、数秒で室温に冷却されてしまうだろう。

いくら激しくお茶をかき混ぜようとも、それ以上に温かくはならないのだ。

C++03とC++14の違い:標準型変換編

京都C++勉強会の宣伝のために、C++03とC++14の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

さて、今回は標準型変換だ。私は便宜上、Starndard Conversionのことを、標準型変換と呼んでいる。

C++14では、リテラルのみが整数nullポインター定数として扱われる。

C++03/11では、コンパイル時に値が0になる整数型もリテラルとして扱われていた。

C++14では、無用の混乱を避けるために、リテラルのみをnullポインター定数とするように改められた。

この違いは、オーバーロード解決などに影響を及ぼす。

void f( void * ) ; // #1
void f( ... ) ; // #2

template < int N >
void g()
{
    // C++03/11では#1を呼ぶ
    // C++14では#2を呼ぶ
    f( 0*N ) ;
}

この例で、依存式、"0*N" は、Nの値がどうなろうと0になる。そのため、C++03では、nullポインター定数として扱われ、オーバーロード解決の結果、ポインター型が最適関数に選ばれる。C++14では、リテラル("0")のみをnullポインター定数と制限したため、0*Nはポインターではなく、#2が呼ばれる。

ただし、C++11/14では、nullポインター定数には、特別なキーワード、nullptrを使うべきであり、0やNULLマクロの使用は、既存のC++03コードを未改変で使う場合のみに留めるべきである。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

当日はUstreamによる配信もある

http://ustream.tv/channel/hatenatech

2013-12-09

Linus、CPUの信頼性について語る

CPU reliability (Linus Torvalds)

2007年のLinusのメールだが、Hacker Newsで話題になっていたので。

From: Linus Torvalds <[email protected]>
Newsgroups: fa.linux.kernel
Subject: Re: [patch] CFS scheduler, -v8
Date: Fri, 11 May 2007 16:52:21 UTC
Message-ID: <[email protected]>

On Thu, 10 May 2007, Pavel Machek wrote:

そもそも、今のCPUは300年も稼働するようには設計されていない。50年以上稼働するハードウェアが設計された後で考えても遅くはない。

そうだな。CPU屋はそういうことをあんまり話したがらないようだな、intel.comをgoogleで検索したらこんなのを見つけた。

故障率と平均故障間隔(Mean Time Between Failure: MTBF)のデータは現在、このWebサイトにはございません。情報についてはIntel® カスタマーサポートまでお問い合わせください。

これは要するに、「俺らそんなこたぁ話したかねーや」ってことを丁重に言ってるんだろう。それが実際に悪いとかじゃなくて、単にそういうことを考えていないのだろうし、CPU屋が、顧客にそういうことを考えてほしい理由もない。

ところで、サーバーのCPUは、たいてい低い周波数で稼働しているが、これはMTBF問題によるものだ。思うに、デスクトップCPUは、たいてい5年間稼働ぐらいのスペックなんだろう。(しかも、電源を落とすこともあるし、たいていの時間はアイドルだ)。しかし、サーバーCPUは、もっと長く稼働するし、もっとアクティブだ。

(「アクティブ」 == 「熱」 == 「原子移動とかのダメージがより大きい等」。オーバークロックすべきでない理由はこれだ。そりゃ、快適に動くかもしれんが、CPUの予測寿命を90%落とすことになる)

もちろん、他の部品にだってMTBFはある。(思うに、電源はたいていCPUより先に壊れるだろう)。もちろん、数十年稼働する機械だってあるにはある。だが、機械はすべて、それほど信頼性を持たないと考えるべきなのだろう。

Linus

私の経験からすると、デスクトップコンピューターで壊れやすいのは冷却のためのファンだ。特にGPUカードに内蔵してあるファンが壊れやすい。もう何度も、GPUのファンが壊れたためにGPUを交換している。また、CPUファンが壊れたこともある。

電源ユニットが壊れたこともあるのだが、どうもこれは、電源ユニットのファンが壊れたらしい。しばらくは動くのにいきなり電源が落ち、しかもやたらとPCケースが熱くなっているので、CPUのファンが壊れたかと思って、よく調べたら、電源ユニット内蔵のファンが回っていなかった。

わたしの経験上、CPUが壊れたことはない。CPUファンが壊れて冷却できずに落ちたことなら度々あるのだが(ケースを開けるまでCPUファンの故障に気が付かず、何度か熱で落ちたが)、熱を検知する保護機能によるものか、CPUは故障しなかった。CPUファンを交換後は、全く問題なく動作した。

私が思うに、ゲーム用の高性能なGPUのビデオカードは、長期間稼働することを全く考慮しない設計になっているのではないかと思う。過去に二台しかデスクトップPCを持っていないのに、グラフィックカードは6枚ぐらい故障のために交換している。これは異常な故障率だ。

C++03とC++11の違い: 字句編

京都C++勉強会の宣伝のために、C++03とC++11の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++11の新しい文字列リテラル

C++11では、新しい文字列リテラルが導入された。特に、その文字列リテラルのプレフィクス、R, u8, u8R, u, uR, U, UR, LRは、C++03では合法なプログラムで違法になるものがある。例えば、そのような名前をマクロを使っていた場合だ。

#define u8 "abc"

// C++03では"abcdef"
// C++11では"def"
const char * ptr = u8"def" ;

このことからもわかるように、Cプリプロセッサーマクロは危険であり、使ってはならない。

C++11のユーザー定義リテラル

C++11では、ユーザー定義リテラルが導入された。これにより、C++03で合法なプログラムで違法になるものがある。たとえば、ユーザー定義リテラルの場所でマクロを使った場合だ。

#define _x "def"

// C++03では"abcdef"
// C++11では、ユーザー定義リテラル
"abc"_x ;

このことからもわかるように、Cプリプロセッサーマクロは危険であり、使ってはならない。

C++11の新しいキーワード

C++11では、以下の新しいキーワードが導入された。

alignas, alignof, char16_t, char32_t, constexpr, decltype, noexcept, nullptr, static_assert, thread_local

これらのキーワードは、C++03ではキーワードではないので、当然、以下のようなコードを記述することができた。

// C++03では合法
// C++11では違法
int alignas = 0 ;

たまたま新しいキーワードを使っていた既存のコードは、C++03では合法だが、C++11では違法になる。

C++では、標準化にあたって、既存のコードで慣習的によく使われている名前をキーワードとすることは避けている。そのため、通常はこれらの新しいキーワードと既存のコードが衝突することはないだろう。

整数の型

C++では、サフィックスを用いていない整数リテラルの型は、その値によって変わる。もし値がint型で表現できない場合long int型、符号付き整数型で表現できない場合、符号なし整数型になる。

C++11では、C99との互換性のため、long long intを取り入れた。このため、C++03では、unsigned long型になっていた整数リテラルが、C++11では、signed long long int型になる可能性がある。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

wandbox-vimで最高のC++14環境を体験

ClangがC++14の機能完全に到達した話はすでにした。しかし、現状ではClangでC++14が使いづらい

今、ClangでC++14を使うためには、まだ安定リリースされていないレポジトリにある最新のglibc、最新のGCC、最新のClangを落としてビルドして配置して適切にパスを通すことが必要になる。そのような作業は面倒すぎて、個人のローカル上ではやってられない。

そもそも、GNU/LinuxでClangとlibc++を適切に配置してパスを通すのも難しいのだ。そのようなパッケージ化は、メンテナーの手によって行われて欲しいが、それには安定リリースを待たなければならない。はやくても来年後半の話だ。

そこで活躍するのがWandboxだ。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

なんと、Wandboxでは、常に最新のレポジトリHEADのClangが使えるのだ。コードを送信すれば、コンパイルして、実行して、結果を返してくれる。

これは素晴らしいが、しかし、コードはVimのような本物のテキストエディターで書きたいものだ。そして、コンパイル程度のことは、Vimから行いたいものだ。

Vimではコマンドを呼び出せる。また、makeには特別な対応がなされていて、コンパイルの処理をMakefileで書いておけば、Vimから簡単に呼び出せる。

そして、VimはGCCのような有名コンパイラーのエラーメッセージをパースして表示し、直接問題箇所に飛べる、quickfixという機能を標準で提供している。

これにより、Vimは何もプラグインをインストールしなくても、コーディングに最適なテキストエディターとなっているのだ。

しかし、Wandboxはオンラインのサーバーで提供されているSaaSSだ。ああ、なんとかしてVimで簡単に扱えないものか。

実は、そのようなプラグインがある。その名も、wandbox-vimだ。

rhysd/wandbox-vim

Wandbox-vimでは、vimで:Wandboxとコマンドを打つだけで、現在のバッファーをWandboxに送って、結果を表示してくれる。

しかもしかも、このwandbox-vimは、機能の更新で、エラーや警告のメッセージをquickfixに流しこんでくれるようにもなったのだ。

今すぐC++14の環境使いたいですよね?

さあ、今すぐアクセス!

GCC 4.9が安定リリースされ、GNU/Linuxのディストロがパッケージ化するまでの間は、とりあえずWandboxでC++14を試すことができる。

2013-12-08

予定のメモ

来週はやることが多いので、メモ代わりに書き出してみる。

16日の夜に、はてなのセミナールームを借りて、江添とボレロ村上の京都C++勉強会を行う

勉強会が終わった後に、ボレロ村上さんを囲んで鍋をする。

17日、おそらく朝は吉田寮にいる。

18日の夜、依頼が会ったので、東京でC++の歴史について講演。(いずれ機会があればスライド資料を使って公開された場でも行うかも)

たぶん卓球ハウスに泊まる。

19日以降、

ギークハウスを見学する。少なくとも、ギークハウス水道橋とギークハウス文京護国寺を見学する。他のギークハウスはどうしよう。

妖怪ハウスにも行く。

さて、これを考えると、18日からその週末まで東京でぶらぶらするべきなのかもしれない。

また、17日のうちに東京入りしてしまうのも手かもしれない。

せっかくだから、この機会に都内のギークハウスに連絡して、行ける場所に一日一件見学に行ってみたい。問題は、東京都内だけでも10件以上あるということだ。

квашеная капустаの肉炒め

квашеная капуста(クヴァーシュナヤ カプーシュタと聞こえる)の肉炒めを食べた。ロシア風のザワークラウトだそうだ。要はキャベツの塩漬けだ。人参が入るのがロシア風なのだとか。

酸っぱいキャベツと肉を一緒に食べると、とてもうまい。

ついでに、日本語入力経由でキリル文字で入力してもらった。

あとで、試みにiBus 1.5でロシア語キーボードレイアウトを追加してみた。キリル文字が打てるようになったが、残念ながら私にはキリル文字は読めないので、もとに戻した。

neobundle.vimのインストール方法

Shougo/neobundle.vimは、Vimプラグインのインストールと管理のためのプラグインである。

インストール方法

まず、GitHubから最新版を引っ張ってくる。私の今使っているネットワークの都合上か、sshでcloneできなかったので、httpsを使う。

$ mkdir -p ~/.vim/bundle
$ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim

次に.vimrcに設定をする。最小限の例は以下のようになる。

if has('vim_starting')
  set runtimepath+=~/.vim/bundle/neobundle.vim/
endif

call neobundle#rc(expand('~/.vim/bundle/'))

" Let NeoBundle manage NeoBundle
NeoBundleFetch 'Shougo/neobundle.vim'

" add plugins

filetype plugin on

NeoBundleCheck

neobundleにプラグインを管理させるのはとても簡単。.vimrcに追加していく。特に、プラグインがgithubで公開されている場合、ユーザー名とレポジトリ名を指定するだけでいい。

" install wandbox-vim
NeoBundle 'rhysd/wandbox-vim'

必要なだけ書いたら、vimを起動して、

:NeoBundleInstall

すればよい。

アップデートしたくなったら、

:NeoBundleUpdate

するだけでいい。

GitHub以外の場合、gitのURLを指定することができる。また、subversionもサポートしているようだ。

それにしても、よくVimプラグインでこれをやるものだ。これまで、@ShougoMatsu さんは、Vimの頭のおかしい人だと思っていたが、なんとVimの変態だったとは。

CとC++の違い: プリプロセッサー編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++では、__STDC__については規定されていない。

__STDC__は、C言語の実装において定義されるプリプロセッサーマクロである。C++はC言語ではないので、このマクロについてC++の標準規格上、なにか規定することはできない。

そのため、__STDC__は、その値と、定義されるかどうかも含めて、何も規定されていない。C++実装はそれぞれ独自に、このマクロの扱いを決めることになる。

しかし、C++はC言語の拡張として発展したという歴史があり、100%ではないものの互換性があるという事情もある。既存のCコードに、このプリプロセッサーマクロに依存したコードがある場合、たとえC++と互換性のあるCコードでも、このプリプロセッサーマクロが定義されていないという理由だけでコンパイルできなくなるかもしれない。そのために、このようなプリプロセッサーは、C言語との互換性が問題になる場合、定義しておきたい。しかしそれは、ある意味嘘をつくことになる。しかし、そもそもそのようなプリプロセッサーに依存するようなCコードの問題もある。

Cプリプロセッサーは滅びるべきなのだ。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-12-07

CとC++の違い: 特別なメンバー関数編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++では、暗黙に生成されるコピーコンストラクターとコピー代入演算子は、volatileオブジェクトをコピーできない。

struct S
{
    int i ;
    // C++
    // 暗黙のコピーコンストラクター
    // S( S const & ) ;
    // 暗黙のコピー代入演算子
    // S & operator =( S const & ) ;
} ;

int main()
{
    volatile struct S s = { 0 } ;

    // Cでは合法
    // C++では違法
    struct S s2 = s ;
}

これは、暗黙に生成されるコピーの仮引数の型が、T const &だからだ。強い静的型付けをもつC++だから、このままではvolatileオブジェクトは受け取れない。

volatileの扱いは色々と難しく、C++では色々と議論された。

暗黙のコピーを、const volatile T &とする案は、最適化の妨げになるという理由で却下された。三種類のCV修飾されたコピーを暗黙に生成するという案は、とても複雑になり、予期しない問題を生むだろうという理由で却下された。結局、このようなコード例は少ないだろうからということで、この点ではCとは非互換になることを決定した。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-12-06

CとC++の違い: クラス編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

今回は、クラス編だ。C++ではクラスを導入したせいで、C言語の構造体とは少し違ったスコープのルールになっている。

C++では、クラス宣言はクラス名をスコープに持ち込む。C言語ではクラス名を持ち込まないし、外部スコープの名前を隠すこともない。

int x[99] ; // #1

void f()
{
    struct x { int i ; } ; // #2

    // Cでは#1のサイズ
    // C++では#2のサイズ
    sizeof( x ) ;
}

これはなぜかというと、C言語では、宣言した構造体名は必ず、structキーワードをつけて使うからだ。C++では、基本型とユーザー定義型の文法に違いを持たせたくないため、クラス名だけで使えるようにしている。そのため、クラス名がスコープに導入される。

C++では、int型のビットフィールドの型は符号付きである。Cでは符号は実装依存である。

int型のビットフィールドの符号を実装依存にするのは、テンプレートの実体化のさいに問題になる。一貫性を保つため、非依存名でも、符号つきになるように、実装の自由度を狭めた。

いくらビットフィールドとはいえ、"int"なのに、符号付きかどうか実装依存というCの定義は不思議だ。

C++では、ネストされたクラス名の属するスコープは、直前の外側のクラススコープである。Cでは、直前の外側のクラスが属するスコープである。

struct Outer
{
    struct Inner { } ;
} ;

// Cでは合法
// C++では違法
struct Inner i ;

C言語はわけがわからない。

どうやら、当時のC言語における構造体というのは、そもそもスコープがどうというものではなかったようだ。そもそも、名前もtypedef名で与えるコードが一般的だったようだし、全然別の言語なのだろう。

C++では、メンバー関数を導入したことにより、クラスは厳格にスコープを持たなくてはならなくなった。それがこの違いを生んだのだろう。それにしても、Cは汚い。

C++では、クラス名ですでにtypedef名が使われた場合、そのtypedef名が再宣言されてはならない。

typedef int I ;

struct S
{
    I i ; // typedef名をすでに使う

    // Cでは合法
    // C++では違法
    int I ;
} ;

たしかこれはD&Eにも書いてあった内容のはずだ。クラスはその完全な定義が明らかになった後に、再び銭湯から解釈した時に、メンバー名の意味が変わってはならないというルールだ。それにしても、Cは汚い。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

OCNモバイルONEのレビュー

好意で、OCNモバイルONEのSIMカードをしばらく貸してもらうことになった。

今回貸してもらったSIMカードの契約内容は、月々1980円で、帯域が500kbps、転送量制限が月あたり7GBで、転送量を超過すると、帯域が200kbpsに制限されるというものだ。

OCN モバイル ONE | OCN プロバイダ(インターネット接続)

何故か公式Webサイトには負の広告効果を発生させそうなデブ女が怪訝そうな顔をしてSIMカードをつまんでいるが、この女がSIMカードの意味を理解しているとは思えない。一体、世の広告業界は何を考えているのだろうか。特に英語力で有名でもない人間に英会話教室の広告をさせたり、特に技術力に優れていると定評のあるわけでもない人間にコンピューターやソフトウェアの広告をさせたりしている。

試みに、筆者が、かければアキバ系の彼でもジャニ系に変身できるというあの伝説のサングラスの広告に出ている場面を想像せよ。およそあり得べからざる光景である。およそジャニ系を名乗るには、髪をだらしなく生やした上で寝ぐせをたっぷりとつけねばならないのである。機能美を何よりも優先する筆者は、頭髪などもとより剃りあげている。頭髪などは本来人間に不要の体毛である。人間がいまだわずかに体毛を維持しているのは、単にヒトが進化の途中であるに過ぎないのだ。

これまでに使っていた、DTIのServerMan SIM LTEは、帯域が150kbps、転送量制限がなし、強制画像劣化圧縮プロクシというものだった。

ServersMan SIM LTE:【dream.jp】

本の虫: 100kbpsで閲覧できるWebサイト、できないWebサイト

この記事を書いた後も色々と試したのだが、このDTIの画像の劣化圧縮のためのプロクシは、かなり厄介だ。というのも、このプロクシが間にあるおかげで、ものすごい遅延が発生する。しかも、このプロクシサーバー、かなり頻繁に不安定になり、コネクションははれるが、一切受信できない状態に陥る。例えば、昨日は一日中、使うことができなかった。

そう、DTIの格安SIMでよく発生している問題は、帯域ではなく、DTIのクソプロクシの問題だと思うのだ。

OCNモバイルONEには、そのような罠はない。500kbpsとは帯域が5倍であるが、帯域以上に、このクソプロクシがなくなったというのが大きい。これで、十分に待てば、どのようなWebサイトでも閲覧できるようになる。

たとえば、通常のGMailのWeb上のUIも少し待てば表示されるし、Google Mapsも少し読み込みに時間がかかるが使える。さらに、Street Viewまで使えるのだ。

もちろん、筆者のコンピューターはOSから上のソフトウェアはすべて自由ソフトウェアのみで構成されているので、Flash Playerは入れていない。同じく貰い物のこのラップトップは、IntelのHD3000を使っており、公式に自由なソフトウェアスタックを使ったドライバーが提供されていて、ドライバー環境はとても綺麗なのだ。Google MapsのStreet viewは、GPU支援があるのか、それともChromiumのソフトウェアエミュレーションかはしらないが、WebGLを使うことで、パフォーマンス上全く問題なく利用できる。

他にも、pixivを画像の超絶劣化なしに閲覧できるし、今は吉田寮にいるので検証できないが(とはいっても、今筆者が座っているこたつの周りにはエロ画集とかも転がっているので、できない理由もないのだが)、おそらくxvideosも問題なく閲覧できることであろう。特に、今回は技術的に面白いこともないので、xvideosは検証しない。特に動かないであろう理由もないからだ。

しかし、今は無線によるインターネット接続が本当にお手軽になってきた。

CRTPと仮想関数呼び出しの比較

Eli Bendersky's website » The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++

CRTPを使えば、コンパイル時に決定できるような派生クラスの関数呼び出しは、仮想関数呼び出しで実行時に解決しなくても、直接呼び出せることになり、仮想関数呼び出しを省略できる。このコストはいかほどか。

アーキテクチャーによっては6倍になるそうだ。

X11の究極の互換性の実証

The Resistor Network: A Testament to X11 Backwards Compatibility

Hewlett Packard 1670A Deep Memory Logic Analyzerという1992年のマシンに、Xサーバーに接続できる機能があるので、Linux Mint 15とe17で試してみたところ、なんと問題なく動いたそうだ。

なんと言うプロトコルの後方互換性。

2013-12-05

CとC++の違い: 宣言編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

今日は、宣言の違いを解説する。

C++では、staticやexternキーワードは、オブジェクトの宣言にのみ使用できる。型の宣言に指定することはできない。Cでは、型の宣言に指定することもできた。その場合、単に無視される。

// Cでは無視される
// C++ではエラー
static struct S
{
    int i ;
} ;

C言語では、合法ではあるが、単に無視されていた文法を、禁止しただけだ。このようなコードはまず書かれていないだろうから、特に問題にはならないだろう。

C++では、同一のスコープ内で、typedef名とクラス名を重複して宣言することができない(ただし、同名のクラスへのtypedef名を除く)。Cでは、構造体名と異なるエンティティで同名のtypedef名を宣言できる

// OK in C and C++
typedef struct S { } S ;

// CではOK
// C++ではエラー
struct name { } ;
typedef int name ; 

なぜC言語ではこれが許されていたかというと、C言語では、構造体は必ずstructキーワードを使う必要があったからだ。

struct S { } ;

// Cではstructキーワードが必須
struct S s ;

C++では、基本型とユーザー定義型を、なるべく区別なく使えるようにしようという観点から、このようなstructキーワードの使用の省略を許した。そのため、クラス名はスコープ内で重複することができなくなり、このような変更が必要となった。

C++ではconstなオブジェクトは必ず初期化されなければならない。Cでは、初期化しなくてもよい。

// well-formed in C
// ill-formed in C++
const int object ;

constオブジェクトは、変更できないわけだ。したがって、constオブジェクトが有益な値をとるには、必ず初期化されなければならない。したがって、C++ではconstは初期化しなければならない。

そもそも、constを導入したのはC++が先で、Cが後から追随したはずだ。C言語というのは不思議な劣化があるものだ。

C++では、暗黙のintを廃止

あー、暗黙のint、あの忌まわしき機能を解説することになるとは、私はよほど前世で悪業を重ねてきたに違いない。

f( const x )
{
    const y = x ;
}

このようなコードが、「暗黙のint」というタイプするのさえ恐ろしい機能によって、Cでは合法になる。関数fの型はint( int )で、変数yの型もintだ。

C++では、autoキーワードをストレージクラス指定子として使えなくなった。

Cでは、autoキーワードは、ローカル変数を自動ストレージ上に確保するための指定子だった

void f()
{
    auto int x = 0 ;
}

ただし、古今のC言語のコードで、autoキーワードを教科書以外で使っているのを見たことがない。なぜならば、ローカル変数はデフォルトで自動ストレージ上に確保されるのだから、わざわざつける必要がないからだ。

C++では、キーワードを再利用して、初期化子の式から変数の型を推定する新機能として生まれ変わった。

auto x = 0 ; // int

C++でこのような破壊的変更を行えたのも、結局、誰もautoキーワードなんか使っていなかったからだ。

C++では、enum型のオブジェクトには、同じenum型のenumeratorしか代入できない。Cでは、どんな整数型でも代入できる。

// well-formed in C
// ill-formed in C++
enum color { Red, Green, Blue } ;
enum color = 1 ;

強い静的型付けを持たないCはどうしようもない。

C++では、enumeratorの型はその属するenum型。Cでは、int型

enum E { value } ;

// C++における式の型はE
// Cにおける式の型はint
value ;

強い静的型付けを持たないCは悲惨だ。

次回は、宣言子の違いについて解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-12-04

CとC++の違い:式編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

今回は式編

C++には関数の暗黙宣言がない

昔のC言語には、関数の暗黙宣言があり、関数名は宣言しなくても使うことができた。C++では、名前は宣言しなければ使えない。

void f()
{
   g() ; // エラー、gは宣言されていない
}

C++では、型は宣言の中で定義しなければならない。C言語ではsizeof演算子やキャスト式の中で定義することもできた。

// Cでは合法
// C++では違法
size_t size = sizeof( struct { int i ; } ) ;

条件式、代入式、コンマ式の結果がlvalueになることがある

C++では、リファレンスにより、関数がlvalueを返すこともできる。

これは、lvalueからrvalueへの変換をあてにしていたCコードを壊すおそれがある。例えば以下のようなコードの挙動が異なる。

char arr[100] ;

// C++では結果は100
// Cでは結果はsizeof(char *)
sizeof( 0, arr ) ;

まあ、この挙動に依存したコードはまれだろう。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++の歴史のスライド資料をGitHubで公開

C++の歴史について話してくれという依頼があったので、そのためのスライド資料を書いた。

依頼主からは独立した内容で、C++の歴史や標準化委員会の実情を書いていて面白いと思うので、GitHubで公開する。

GitHub: EzoeRyou/cpp-history

GitHub Pages: C++の歴史

まだまだ加筆するかも知れない。

今回の依頼主の講演は非公開だが、いずれ個人的に勉強会を開いて、このスライドを使った発表もしたいものだ。

結局、自由なものに金をだすというのは、こういうものを作るのに金を出すということになるのだろう。金を出さなくても誰かがいずれ書くかも知れないが、それは数百年後かも知れない。今欲しければ、金を出して書ける者に書いてもらうのが手っ取り早い。

2013-12-02

CとC++の違い: 標準型変換編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

今回は標準型変換の違い。

C++では、void *から任意のポインター型への変換には明示的なキャストが必要

C言語では、void *型は特殊な型で、任意の型へのポインター型をvoid *型に暗黙に型変換できるし、またvoid *型から任意の型へのポインター型に暗黙に型変換できた。

// Cコード

int * ptr = NULL ;
void * v = ptr ; // OK
int * i = v ; // OK

C++では、void *への変換は暗黙にできるが、void *から他の型への変換は、明示的なキャストが必要になった。

// C++コード

int * ptr = nullptr ;
void * v = ptr ; // OK
int * i = static_cast< int * >( v ) ;

明日も、宣伝のために式の変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-30

100kbpsで閲覧できるWebサイト、できないWebサイト

今、私が常時使えるネット回線は、DTIの提供する格安のSIMカードを利用したLTE経由のものだ。利用料金は月々490円+ユニバーサルサービス料3円となっている。

とてつもなく格安だが、極端な制限がある。帯域が100kbps、今は実験的に150kbpsに制限されているということだ。転送量制限はないのだが、この帯域は、2013年にはなかなかに厳しい。

私は、まだ56Kbpsのアナログモデムの頃からインターネットを利用しているが、もはや最低でも数Mbpsは当たり前になったこの時代に、100kbpsは、結構難しいところもある。使えるかどうかは、Webサイトにより異なる。

今、風邪をひいて体調が悪く、外に出れないのを幸いに、この低帯域でできることを試してみることにした。

まず、まともに閲覧できないWebサイトだ。

例えば、GMailのような、巨大なJavaScriptでできたプログラムで、常にサーバーと通信しているようなWebサービスは、かなり使いづらい。GMailのWeb UIには遅いネットワーク版もあるが、これでも100kbpsでは使いにくい。

結局、問題は帯域なのだ。あらゆる通信は100kbpsの帯域を通らなければならないのが問題なのだ。これら、数百キロバイトから数メガバイトもあるような巨大なJavaScriptプログラムをダウンロードするだけで時間がかかる。また、それだけではなく、そのJavaScriptプログラムは、さらにサーバーと通信を行う。

単に時間がかかるというだけではない。詳しい理由はわからないが、通常のGMailはたいてい、いくら待っても使えない。何度かリロードしてようやく使えるようになる。思うに、HTTPやHTTPSプロトコルを使い、複数のファイルを同時にダウンロードしようと試み、それがすべて狭い100kbpsのネットワークを通過しなければならないため、どのファイルもダウンロードが完了せずに延々とちびちび読み込み続けているのではないかと思う。通常のGMailは極端な低帯域は考慮していないようで、そういう場合に、いくら待ち続けようとも、延々と読み込み中の画面を表示し続ける。何度かリロードすると使えるようになるというのは、あるいはファイルの一部がキャッシュされてダウンロードしなくても済むため、並行ダウンロードが減少し、GMailのJavaScriptプログラムでも動く程度の時間でダウンロードできるようになるのではないか。あるいは、あまりに時間がかかりすぎるため、JavaScriptプログラムかブラウザーのどちらかがダウンロードを諦めたのか。

はたまたあるいは、これらのサイトがHTTPSプロトコルを使っているからなのかもしれない。あまりに低帯域でHTTPSプロトコルを使うとこういう問題に出くわすのかも知れない。

ひとたびGMailの巨大なJavaScriptプログラムが動きさえすれば、あとは快適に使えるのだが。

TwitterのWebサイト上のUIも、同じ問題を抱えている。Twitterのページを読み込む際に、他にも、別のページやファイルなどのダウンロードが発生している場合、たとえ別のページやファイルのダウンロードが終わって、帯域が空いても、読み込み中のまま一向に進まないことがある。

Googleの検索も、同じ問題を抱えている。

YouTubeは、動画の再生はともかく、極小のサムネイルの表示まで遅い。

では、まともに閲覧できるWebサイトは何か。

基本的に、テキストを主体とし、JavaScriptで高度で頻繁な通信を行っていないようなページは、問題なく表示できる。Hacker Newsも問題ない。[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッも問題ない。

意外なところでは、pixiv.netが快適に閲覧できるということだ。サムネイルの表示も十分に速い。もちろん、100kbpsなので、個々の画像をダウンロードして表示するのにはそれなりに時間がかるが、このサムネイル画像の速さは大したものだ。また、pixivはHTTPSを使っていないことも影響しているのかも知れない。しかし、それをいえばYouTubeだってHTTPSではないのは同じだ。しかも、pixiv以上に小さいサムネイル画像の表示が遅い。

あるいは、YouTubeを閲覧する利用者のネットワークは、そもそもそれなりに広い帯域が必要であろうから、手描き画像に特化したpixivほど低帯域ユーザーの需要がないのかも知れぬ。需要がなければ供給もない。Yahooが既存の広告媒体よりは安いが、ネット広告としては高すぎるのに、無知な広告主によって払われる多額の広告料にあぐらをかいて技術革新を怠り、Googleに追いぬかれたように、需要は重要である。

はて・・・低帯域ユーザーでも変わらず需要があるものとなると・・・

深い技術的好奇心の念に駆られた筆者は、あくまで知的探究心のために、xvideos.comを閲覧した。

Lo and behold!

すると見よ! わずか100kbpsの低帯域だというのに、YouTubeよりはるかに大きな、しかも大量のサムネイル画像が一瞬にして表示され、マウスカーソルを当てるとコマ送りまでするではないか。

筆者は慄然とした。今にして始めて芸道の深淵を覗き得た心地であった。

誠に残念ながら、OSから上は自由なソフトウェアのみで構成された筆者のコンピューター環境にはFlash Playerがなく、したがって、100kbpsのネットワーク越しに動画を再生できるかという肝心の主要機能に関しては、技術上非常に興味はあるものの、遺憾ながら検証できなかった。ただ、おそらくうまくやるのではないかと思う。

無論、これは今に始まった話ではない。エロサイトの動画プレイヤーの方が、YouTubeよりよっぽど優れているというのは、昔から言われていたことだ。

本の虫: なぜエロサイトの動画プレイヤーはYouTubeより高機能なのか

このようなエロサイトは、厳しい競争にさらされている。収益をあげるためには、できるだけ多くの閲覧者を得る必要がある。広告収入を得るにしても、課金収入を得るにしても、とにかく大量の閲覧者を集めなければならない。そのためには、低帯域ユーザーが閲覧できないということは、取り逃すことのできない機会損失なのだろう。それにしても・・・

論語に言う、いまだに色を好むが如きものを見ざるとはこのことか。

追記:pixiv.netとxvideos.comが快適な件について、少し事情が異なった。

ご注意事項|ServersMan SIM LTE:【dream.jp】

DTIの格安SIMカードを経由してHTTPプロトコルによりダウンロードされる、画像フォーマットのうち、JPG, GIF, PNGは、DTI側で自動的に劣化圧縮される。

xvideos.comで確認したときは、まあ、エロサイトだしこんなものかと思っていたのだが、さすがに引越し前まで毎日見ていたpixivは気がついた。

何のことはない。HTTPSプロトコルが遅いと感じていたのは、中間で乗っ取りできないからだったのだ。pixivやxvideosが快適に閲覧できたのは、画像を劣化圧縮していたからなのだ。

というわけで、この記事は当初の面白い記述から遠ざかってしまった。この記事を書くときは、「やはりエロ需要の力は偉大だ」という、あからさまに面白い結果になったと早合点して、そのように面白おかしく書いたのだが、現実はそれほど面白くはなかった。残念。

2013-11-29

Clangで-std=c++1yがいまだに使いにくい事情

ClangがC++14の機能完全に到達したことはすでに述べた。これはつまり、最新版のClangで、-std=c++1yを指定すると、現在のC++のドラフト規格の、動く実装が手に入るということだ。

これは素晴らしいことだ。

しかし、いざ実際にUbuntu 13.10でClangのSVN HEADを自前ビルドして使ってみようとすると、以下のようなエラーが表示される。

/usr/include/c++/v1/cstdio:156:9: error: no member named 'gets' in the global namespace

ヘッダーファイルを一切includeしなくても、このエラーは表示されてしまう。

この事情は・・・結構複雑なのだ。

C++14では、Cの標準ライブラリは、C11のものに合わせられた。C11の標準ライブラリでは、とうとうあの忌まわしき太古の呪いである、getsを廃止した。廃止である。非推奨ではない。C11では、もはやgetsは存在しないのだ。

したがって、C11やC++14モードでコンパイルするには、このgetsを#ifdefで囲むなどして、取り除く対応をしなければならない。

しかし、現行の多くのGNU/Linuxの安定版ディストロが使っているglibcのバージョンは、まだこの変更に対応していない。

それもそのはずで、C11のgets廃止に対応したglibcを使うには、GCC 4.9が必要なのだ。GCC 4.9は、まだ開発途中で安定リリースされていない。そんなGCCをデフォルトで出荷するGNU/Linuxディストロなどあるはずがない。

GNU/Linuxにおいては、libcのような基本的なライブラリと、C++コンパイラーは密接に関係していて、単にコンパイラーだけを自前ビルドして使うわけにはいかないのだ。

したがって、もし自前ビルドするとなると、ClangとGCC一式を完全に自前ビルドした上で、ライブラリへのパスを自前ビルドのglibcに通すなどしなければならない。おっと、C++標準ライブラリも、libc++を使いたいし、ABIライブラリも悩ましい。これらのコンパイラーとライブラリを正しく配置して正しくパスを通すのは、とても面倒なのだ。

やればできるだろうが、こんな面倒なことはやりたくない。私はおとなしく、GCC 4.9が安定リリースされて、GNU/Linuxディストロで、ソフトウェアがプロの手によってパッケージ化されるのを待つことにする。

とはいっても、とりあえずC++14の新機能を試してみたいものだ。実は、そんなあなたにうってつけのSaaSSがある。

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

melponさん、ありがとよ。

なんと、Vim用のプラグインまである。

rhysd/wandbox-vim

Linda_ppさん、ありがとよ。

参考:

Bug 13566 – Glibc should define gets for C++11

Bug 51785 – gets not anymore declared

2013-11-28

12月18日に東京に行きそうな予定

どうやら、12月18日に東京に行く機会がありそうだ。

今回は、表立った発表ではないが、魔導書の記事執筆依頼、数年ぶりにC++の歴史をまともに調べた。といっても、大方はD&EやHOPL2, HOPL3を読み返しただけなのだが。HOPL-3以降の歴史は、現在進行形で私も追っているし、まだ現在のことなので、Stroustrupがまとめるほどではない。ただ、いずれStroustrupの視点でまとめたHOPL-4がでれば、読みたいとは思う。

また、今となっては死んだEC++についても、いい機会なので、最初から最後まで関わっていた人物から、改めて話を聞いた。

その結果は、まだスライド資料として執筆中だが、とりあえず資料だけでも、12月中に公開しておこうと思う。

今のところの予定としては、とりあえず18日は卓球ハウスに泊めてもらい、18日か19日に、誰かと食事にでも行ければと考えている。

CとC++の違い: Basic Concepts編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++はCの完全互換ではない。Cのあまり良くない部分は、変更して改良した。ここでは、そのような変更点のうち、互換性に特に問題のあるものを取り上げる。

tentative definitionの有無

C言語には、tentative definitionという機能があった。以下のようなコードが合法になる。

int i ;
int i ; // well-formed in C, ill-formed in C++

C++にはOne Definition Ruleがあるので、このようなコードは違法である。

C言語に存在するtentative definition機能は、定義の後で初期化できるという機能を提供している。

struct X { X * next ; } ;

X a ; // 定義
X b = { &a } ;
X a = { &b } ; // 初期化

C++では、基本型とユーザー定義型で別々の初期化ルールを設けるのを防ぐために、tentative definition機能はCから受け継がなかった。

structにはスコープがある

C++では、structは構造体ではなくクラスであり、新たなスコープを作る。Cではstructは、単なる構造体であり、その名前探索の挙動が異なる。

ただし、通常はこの差を気にする必要はない。

ファイルスコープ内で、const修飾され、extern指定されていない変数は、C++では内部リンケージとなる。Cでは、外部リンケージとなる。

// file1

// Cでは外部リンケージ
// C++では内部リンケージ
const int x = 0 ;
// file2

// Cではfile1のxを指す
// C++は違う
extern const int x ;

C++では、constオブジェクトは、コンパイル時定数となることもあるので、初期化子が必須なこともあるので、このような変更がなされた。

C++では、main関数を再帰的に呼び出すことはできず、アドレスを取得することもできない。

C++では、main関数は特別なものとして認識され、呼び出すことはおろか、アドレスを得ることさえできない。Cでは、そのような制限はない。

C++でこのような制約がある背景事情としては、mainは特別な扱いであるべきで、その実装方法に関して、C++の実装に、通常のような関数として扱えるような制約を持たせたくないというものがあるそうだ。

Cで書かれたmain関数を再帰呼び出ししたりアドレスを得たりするコードを移植する際には、単にmain関数から呼び出される別名で同じ仮引数の関数を作ればいい。そもそも、main関数を再起呼び出ししたりアドレスを得たりするような実用的なコードは、あまり存在しないだろう。

C++にはCompatible type(互換型)が存在しない

Cには、互換型というものが存在する。例えば、タグ名以外はすべて同一の構造体などが該当する。C++は強い静的型付けを持っているので、そのような互換型は存在しない。

Cでは、そのような型非安全なコードは多いのではないかと思う。

明日も、宣伝のために標準型変換の変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-27

CとC++の違い:字句編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

C++はCの完全互換ではない。Cのあまり良くない部分は、変更して改良した。ここでは、そのような変更点のうち、互換性に特に問題のあるものを取り上げる。

今回は、字句編だ。

新しいキーワード

C++では、新しいキーワードが追加されている。C++で追加されたキーワードを名前に使っているようなCコードは、問題になる。

文字リテラルの型がintからcharに変更

Cでは、'a'の型は、intだった。これは、オーバーロード解決で問題になる。

// 実装依存の整数が出力される
std::cout << 'a' ;

C++では、文字リテラルの型をcharに変えた。

これにより壊れる可能性のあるコードとしては、sizeof('x')のようなコードが想定されている。しかし、そのようなコードはあまり多くないだろう。

文字列リテラルの型がconstになった。

Cでは、文字列リテラルの型はconstではなかった。C++ではconstだったが、C++03までは、文字列リテラルに限り暗黙にconstを消し去ることを認めていた。C++11では、そのような標準変換もなくなったので、以下のようなコードはエラーとなる。

// エラー
char * ptr = "hello" ;

このようなコードは、そもそも適切ではない。文字列リテラルの指し示すストレージを書き換えた結果は未定義だからだ。案外まだ、このような不適切なコードは残っているのではないだろうか。

明日も、宣伝のためにBasic Conceptsの変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

2013-11-26

ラップトップ用のインナーケースを買った

新しい15.6インチのラップトップを譲り受けたことはすでに述べた。このラップトップのパフォーマンスは申し分ないが、少々大きい。大きいのはいいのだが、最近はラップトップを持ち運んで、家の外で作業をすることが多い。その持ち運びがやや不便だ。

私は、昔使っていた13か14インチのラップトップ用のカバンを持っている。このカバンは、ラップトップを固定するためのポケットが付いているのみならず、背負うこともできれば手持ちのとっても縦横二箇所についているし、肩から下げる取り外し可能なヒモも付いているという、結構多機能なカバンなのだ。ただし、だいぶ傷んできて、背負いヒモの縫い目も危なげにみえるし、15.6インチのラップトップがポケットに入らない。ポケットに入れずに直接入れると、他にいくらも入らないし、他にもACアダプターやマウスやキーボードなどが直接あたって危なげだ。

私は、安いが高機能なリュックを持っている。腰で固定するヒモがあるし、外側から引っ張って中身を固定するためのヒモも四カ所についているリュックだ。このリュックは悪くないが、ラップトップを固定するためのポケットがついていない。このリュックに、他の荷物とともにラップトップを入れるのは怖い。

しかし、毎日ラップトップを持ち運ぶという事情もあるので、やはりなにか一つ、ラップトップ用のカバンを買わなければならないだろう。背負いヒモもついているものがよい。

大型の家電量販店に行って、色々とみてみたが、どうもいいものがない。カバンには背負いヒモがついていない。ラップトップ用のポケットがあるリュックもたくさん売っているのだが、どれもリュックとしては甚だ貧弱なのだ。しかも、値段も1,2万円する。質が低すぎて、値段に見合っていない。一体これはどういうことだろう。

色々と考えた結果、ラップトップ用のインナーケースを買うことにした。インナーケースはどんなに高いものでもせいぜい数千円なので、たとえ失敗しても数万円のカバンやリュックよりはましだ。インナーケースならば、カバンやリュックは別に高品質なものを使えばよい。

どのくらい頼れるのかはわからないが、撥水加工された表面で、適度に硬くて四隅も丈夫で、面はクッションになっているものを買った。

コンパイル時zip関数の書き方、並びに京都C++勉強会の案内

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

さて、昨日は、コンパイル時zip関数を書いた。ただし、コードだけで解説が欠けていた。今日は、解説をしようと思う。

zip

本の虫: 久しぶりにメタプログラミングらしいメタプログラミングをした

以下のような関数

template<std::size_t N, typename... T>
auto zip(const std::array<T, N>&... containers)
    -> std::array < std::tuple < T ... > , N >

が、以下のように動く。

std::array<int, 5> a = {1, 2, 3, 4, 5}; std::array<char, 5> b = {'a', 'b', 'c', 'd', 'e'}; zip<5>(a, b); // -> std::array<std::tuple<int, char>, 5> : (1, 'a'); (2, 'b'); ...; (5, 'e') std::array<int, 4> c = {1, 2, 3, 4}; zip<4>(a, c) // -> compile time error std::vector<int> d = {1, 2, 3, 4, 5} zip<5>(a, d) // -> complie time error

これ自体は、実行時関数ならば、以下のように書ける。

template < std::size_t N, typename ... Types >
auto zip_runtime( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    std::array< std::tuple< Types... >, N > result ;

    for ( std::size_t i = 0 ; i != N ; ++i )
    {
        result[i] = std::make_tuple( containers[i] ... ) ;
    }

    return result ;
}

と、このように簡単なコードなのだが、これはconstexpr関数にできない。無駄なループがある。このようなコードは、リスト初期化を使えば、以下のように書ける。

std::array< std::tuple< Types... >, N >{
    { std::make_tuple( containers_0[0], containers_1[0]) },
    { std::make_tuple( containers_0[1], containers_1[1]) },
// ...
} ;

こういう形に落としこんでしまえば、最初から初期化としてarrayを構築できるし、constexpr関数にできる。

containersは、パック展開でいくらでも展開できるが、添字をどうにかしたい。これにはInteger Sequenceと呼ばれているテクニックを用いることができる。原理はN3493で解説されていて、C++14の標準ライブラリに入るのだが、残念ながら、C++11で実装しなければならないので、これを実装しなければならない。この論文と実装例は、すでに簡易レビューで紹介している。

本の虫: C++ 2013-01 mailingの簡易レビュー

template< std::size_t ... >
struct index_seq { } ;

template < std::size_t N, typename T >
struct make_index_seq_impl ;

template < std::size_t N, std::size_t ... I  >
struct make_index_seq_impl< N, index_seq< I ... > >
{
    using type = typename make_index_seq_impl< N-1, index_seq< N-1, I... > >::type ;
} ;

template < std::size_t ... I  > 
struct make_index_seq_impl< 0, index_seq< I ... > >
{
    using type = index_seq< I... > ;
} ;

template< std::size_t N >
using make_index_seq = typename make_index_seq_impl< N , index_seq< > >::type ;

これは、単にNを指定すると、0,1,2,3... Nまで整数型の非型テンプレートパラメーターパックを生成するための、簡単なメタ関数だ。この実装は簡易的なもので、テンプレートの再帰深度が線形に増えていくが、今回は特に問題としない。

ここまではいい。ではさっそく、これを使ってリスト初期化に展開されるコードを書こう。

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { 
        // エラー
        std::make_tuple<I>( containers[I]... )...
    } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

残念ながら、これエラーになる、なぜなら、パラメーターパックが2つもあって、その数も同じではないからだ。そのため、パック展開に失敗する

C++ Templates Metaprogrammingに書いてあるように、問題があるときは、もう一段階の参照を挟んでやるとよい。ここでは、パック展開されたコンテナーをパラメーターパクで、添字を非パラメーターパックで受け取ってtupleを返す関数を追加する。

template < std::size_t I, std::size_t N, typename ... Types >
constexpr auto make_unpacked_tuple( std::array< Types, N > const & ... containers )
    -> std::tuple< Types ... >
{
    return std::make_tuple( containers[I]... ) ;
}

このもう一段階の参照を使えば、以下のように書ける。

template < std::size_t N, std::size_t ... I, typename ... Types >
constexpr auto zip_aux( index_seq< I ... >, std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return std::array< std::tuple< Types ... >, N >{ { make_unpacked_tuple<I>( containers... )... } } ;
} 

template < std::size_t N, typename ... Types >
constexpr auto zip( std::array< Types, N > const & ... containers )
    -> std::array< std::tuple< Types... >, N >
{
    return zip_aux( make_index_seq< N >(), containers ... ) ;
}

このように書けば、constexpr関数にできるzip関数の出来上がりだ。わざわざループで代入しなくても、構築時のリスト初期化で済ますことができる。

さて、冒頭でも書いたように、江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能や、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド