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日までの日記

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

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の補完とローカルでのコンパイルができるようになりたい。