2014-03-16

妖怪ネットワークにRTX810を導入した

筆者の住んでいるシェアハウスである妖怪ハウスのネットワーク環境、すなわち妖怪ネットワークの構築が、一段落した。ついに、YAMAYAのRTX810を導入することに成功したのだ。

RTX810の初期設定は、一般家庭で使うにはかなり変わっているので、結構な設定が必要だった。

まず、初期設定では誰でもログインできるようになっているので、適切にパスワードを設定した。

デフォルトで設定されるファイヤーウォールが不思議だ。まだRTX810独自のコマンドを読むのに慣れていないのだが、どうもデフォルトで設定されるフィルターは、プライベートIPアドレス間での通信、つまりプレイベートネットワーク内のホスト同士での通信を完全に遮断しているように読める。実際に、RTX810を介して無線LAN APにログインできないので、正しいのではないかと思う。

さらに、ファイル共有で使われるSMBプロトコルも遮断しているように読める。

無線LAN APへのログインは滅多に行わないし、行う場合は無線LAN APについているLANポートと有線接続すればいい。しかし、SMBは妖怪ネットワークの住人の間でも多用されているので、これはまずい。このフィルターは削除した。

また、この調査の過程で、妖怪ネットワーク内で、重要な機密性のあるファイルが存在するディレクトリを、意図せずにパスワード無しでSMBプロトコルで公開してしまっている住人を発見したので、注意して直させた。

RTX810を妖怪ハウスに導入するにあたっての問題は、その接続方法であった。

妖怪ハウスネットワークとインターネットを接続するのは、フレッツ光で、ISPからレンタルしているPR-400MIというモデム兼ルーターを使わなければならない。妖怪ネットワークのパフォーマンスの低さは、まともなスイッチングハブを導入することでかなり改善されたのだが、せっかく強力なルーターであるYAMAHAのRTX810があるので、これを活用してみたいところだ。しかし、どうやってRTX810を直接つなげればいいのだろうか。

まず考えられるのは、PR-400MIにRTX810をつなげて、PR-400MIのDHCPを無効にし、プレイベートネットワークはRTX810で引き受けることである。PR-400MIにはPPPoEブリッジ機能もあるので、RTX810は、PR-400MI経由とはいえど、直接PPPoEを話すことができる。これは動くし、実用上は問題ないだろうが、どうも気分的にやりたくない。

PR-400MIは、一体型のように思えるが、実は、モデム部分とルーター部分が内部で独立しており、モデムとルーターの間を、Ethernetでつなげるようになっている。モデム部分から、UNIと書かれたLANポートがでており、ルーターからのLANケーブルが刺さっている。すると、このUNI LANポートにRTX810をつなげば、完全にISPレンタルルーターを介さずにインターネットにつなげるではないか。

問題は、PR-400MIも、必要だということだ。住人の中に、FAXのために光電話を必要とする者がいるので、光電話は必要である。光電話を使うには、PR-400MIか、光電話をサポートしたルーターが必要である。RTX810は、光電話を使うような用途には想定されていないので、当然、光電話機能はない。すると、PR-400MIもUNIポートに接続しなければならない。

すると、気分的にあまりよろしくないが、やはりPR-400MI経由のPPPoEブリッジで我慢するしかないのだろうか。

Twitter上で、UNIをスイッチングハブで分けて、PR-400MIとRTX810のWANを接続すればいいではないかという助言をもらった。それだ。スイッチングハブでUNIを分けるという単純な発想に、なぜ思い至らなかったのか。

そうして、昨日一日作業して、妖怪ハウスのネットワークをRTX810に移行させた。

それにしても気になるのは、スイッチングハブはどうやってUNIとPR-400MIとRTX810をさばいているのだろうかということだ。このスイッチングハブの利用には、ルーターは一切絡んでいないような気がする。3本の接続は、スイッチングハブからは、どれも平等に見えているのではなかろうか。RTX810の発したパケットは、PR-400MIではなくUNIに届いて欲しいのだが、どうやって動いているのだろうか。スイッチングハブからどうやって見分けているのだろうか。

ネットワーク周りも基礎から真面目に学ばなければならない。

そして、RTX810をDNSキャッシュサーバーとして動作させると、nslookupは使えるのだが、digが使えなくなる。

dig example.com

が動かない。DNSサーバーのアドレスは、127.0.1.1であるので、digで指定してみたが、やはり通らない。

dig @8.8.8.8 example.com

は通る(8.8.8.8はGoogleが提供しているDNSサーバー)

nslookupは使えるし、その他のDNS lookupは問題ないようだ。digがなにか特殊なことをしているのであろうか。RTX810に何らかの設定項目があるのだろうか。

しかし、既存の妖怪ハウスの住人が、どうやって貧弱で不安定なネットワークで暮らせていたのか謎だ。筆者がまともなネットワークを構築するまでは、妖怪ネットワークは極めて不安定で遅延もひどかったのだ。(というより、ほとんどの問題は、RTX810導入以前にまともなスイッチングハブをひとつ導入するだけで解決されてしまった)

改善前の妖怪ネットワークは、一度TCPコネクションをはれば、切れることはないものの、それ以外は極めて不安定だった。

詳しく調べていないのでよくわからないが、たとえば、帯域には波があった。実験のために、十分な帯域を持ったインターネット上のサーバーからダウンロードを行ってみると、数秒100Mbpsを超えたと思えば、数秒間何の転送も行われないような、極端な帯域の波があった。わざわざ、誰も帯域を使っていなさそうな時間帯に試験したのにこれだ。また、ブラウザーで新しいページを開くときに、何十秒も待たされることがたびたびあった。DNS lookupが遅いのか、TCPコネクションを張るのが遅いのか、あるいは単に、先ほど観測された帯域の波という謎の現象のせいなのか、よくわからない。

また、リビングに設置されている無線LAN機器もひどかった。BUFFALO製の機器で、最高54Mbpsでしかリンクできなかった。おそらくはIEEE 802.11nに対応していない機器なのだろう。それだけならまだ許せるが、なぜか数Mbps程度のリンク速度しかでない場合がほとんどだった。どんなに適切な場所を探しても、一向にまともなリンク速度がでない。しかも通信も不安定だった。そんなよくわからない無線LANルーター(APモードで動作)をハブ代わりにして、すべてのLANポートにケーブルが刺さっていた。

筆者のネットの利用方法として、ブラウザーでブックマークしたURLを数十個一気に開いては確認して閉じるようなことをしているので、妖怪ハウスのネットワークの不安定さは耐えられないほどであった。

さて、今回、私が使う部分のネットワークは、私が金を出してまともにした。私が使わない部分に関しては、そのままにしてある。ただし、ネットワーク全体がまともになったので、私の使わない部分も恩恵は受けているが、現時点では、私の使わないところの大部分は完全に潜在的な性能を引き出していない。私の責任ではない。理由は後述。

妖怪ハウスにおいて、筆者はリビングの横の部屋に住んでいるのだが、住人の過半数は、リビングからは離れた部屋群に住んでいる。この部屋群に向かって伸びているLANケーブルがささったスイッチングハブのLEDを確認すると、なんと100Mbpsでしかリンクしていなかった。しかも、LANケーブルの先は安物のBUFFALOの無線LANルーター(APモード)につながっていて、もちろんこの無線LANも、IEEE 802.11nに対応していないため、リンク速度は最大54Mbps。ほとんどの住人はその無線経由でネットワークにつながっている。一人だけ、無線LANルーターをハブ代わりにして有線を部屋に引き込んでいる。

この部屋群のネットワークは、物理的に観測しても悲惨である。LANケーブルが無造作に床をはっているし、無線LANルーターも、固定されずに床に落ちている。以前は床にテープで固定していたらしいが、剥がれたらしい。当然だ、床に固定するから蹴り飛ばされるのだ。

あまりにみかねたので、配線だけはすこし直した。LANケーブルを壁にはわせるようにし、無線LANルーターも壁に固定した。

その際に調査を行ったところ、LANケーブルは1Gbpsのリンク速度がでた。すると、100Mbpsのリンク速度しかでないのは、このBUFFALOの機器のせいだろう。

これをまともにするには、8ポート(あるいは部屋ごとにさらにスイッチングハブで分けるのならば4ポートでも可)ぐらいのまともなスイッチングハブと、まともな無線LAN APに取り替えればよい。そうすれば、各部屋に有線LANとまともな無線LANが行き渡る。筆者はこの部屋群は使わないので、さすがにそこに金を出すことはしない。

結局、インターネット回線はフレッツ光なので、帯域は下り200Mbps/上がり100Mbpsだ。したがって、100Mbpsでも、それほどの問題はないと思うかも知れない。しかし、それはあくまでインターネット回線との間の帯域だ。妖怪ネットワーク内には、もっと広帯域が必要なのだ。妖怪ハウスでは、SMBプロトコルによるファイル共有を行っている住人が多い。当然だ。リビングまでストレージを担いでやってきて作業したい者などいるわけがない。そして、住人の大半は部屋群に集中している。この構成では、部屋群の誰かがSMBプロトコルで自分のストレージに本気でアクセスしただけで、部屋群全体のネットワーク帯域がほとんど使い尽くされてしまうはずだ。なぜならば、部屋群は全体で100Mbpsしか帯域がないからだ。

ただ、部屋群の住人は、以前の悲惨なネットワークでも、改善するほどの不満はなかったのだから、それほど帯域を使っていないのかも知れない。実際に聞けば、最近はファイル共有を使っていないという。

ともかく、妖怪ネットワークは快適になった。

Samsung Galaxyにバックドアが発見される

Googleとハード屋が不自由なソフトウェアを世の中に蔓延させるために不毛な労力を注ぎ込んでいるAndroidは、無論、不自由なOSかつ、制限ハードウェアである。

確かに、Androidは、時代遅れの自由なソフトウェアライセンスであるGPL Version 2であるLinuxカーネルを使っているものの、そのlibcは、許諾的な自由ソフトウェアライセンスであるBSDライセンスされたBionicであり、その下に、不自由なバイナリブロブのドライバーが山ほど動いている。そして、Androidを搭載しているほとんどのハードウェアは、極めて屈辱的に制限されている。

ほとんどのAndroidハードウェアは、二つのCPUを積んでいる。ひとつは、Androidや、その上の通常のユーザーランドのソフトウェアを動かす、汎用CPUである。Androidは手足をもがれて不自由ソフトウェアに汚染されたOSであるが、まだ多くの共通部分は公開されているといえる。

もうひとつは、モデムとかベースバンドとかラジオなどという名前で呼ばれているCPUで、電話局との通信の制御に使われている。このCPUが動かすOSやソフトウェアは、完全に閉鎖的でプロプライエタリで、どうしようもないクソだ。我々はこの動作を、たやすく検証することはできない。極めて信頼できない、危うい組み込みのスパイである。

参考:The second operating system hiding in every mobile phone

さて、今回、Replicantという完全に自由なAndroidディストリビューションを開発しているプロジェクトが、邪悪な意図の存在が極めて強く示唆されるSamsungのほとんどのGalaxyデバイスに、バックドアを発見したと発表した。

SamsungGalaxyBackdoor - Replicant
Replicant developers find and close Samsung Galaxy backdoor — Free Software Foundation — working together for free software

どうやら、このベースバンドCPU上で動くプロプライエタリな怪しいOSと、GalaxyにプレインストールされたAndroidに搭載されたカーネルモジュールが協調して、ファイルシステムに無制限にアクセスできる、その意図が疑わしい機能が含まれているという。これは、バックドアとして悪用可能である。

完全に自由なAndroidディストリビューションを開発するReplicantでは、そのような疑わしいカーネルモジュールなど搭載することはなく、したがってこのベースバンドCPUの上で動くプロプライエタリOSと強調することはなく、したがって、このようなバックドアの疑いが強い機能の動作を阻止できる。

既存のSamsung Galaxy利用者は、今すぐSamsung Galaxyデバイスのバッテリーを引っこ抜いて窓から放り投げるか、少なくともプレインストールされた不自由Androidを完全に削除し、新規にReplicantをインストールして、Samsungに説明を要求するべきである。

あるいは、ハンロンの剃刀に従えば、これはベースバンドOSが、デバッグ目的などで手軽なストレージを扱いたかったので付け加えたあくまでデバッグ目的の小汚い機能が、製品版でも取り除かれずにそのまま残ったのかも知れない。一般に、この手のQualcommなどのハード屋は、どうしようもないほどバカでマヌケで底なしに無能であり、そういうことは十分に考えられるからだ。

ここにいるぞ。中は想像以上に悲惨だ。コードが公開される時--すなわちネット上にばら撒かれるせよ、あるいはもっと悲惨なことに、正式にビジネスパートナーに提供されるにせよ--その時はすでに、全開発者は、新規のプロジェクトにとりかかっている。コードがコンパイルされて、製品として店先に出荷されるまでには、6ヶ月ほどのラグが存在する。その時には、すでに技術は移り変わっているので、誰も大昔のものには関心を払わない。すでに出荷されたものの不具合を修正することに、何の利益もないし、企業的理念も存在しない。コードをパッチするなんて簡単なことであると、私は常に思っていたのだが、管理職の連中にとっては、大事でも何でもないことであった。

BNC43xxの開発における、本当にクソすぎたことを教えてやろう。我々は3ComとかLinksys(Ciscoに買収される前後両方)とかAppleとかD-Linkとかに、リファレンスデザインを販売していた。理屈の上では、全社とも、同じリファレンスデザインを受け取るわけだ。だが、もしそのうちの一社が我々のコードのバグ報告をしたならば、パッチされたコードを受け取るのは、バグ報告したその一社のみだ。結果として、我々のコードには、#ifdef(COMS)とか#ifdef(LINKSYS)とかで、それぞれ専用のパッチを有効にしてあった。まだバグを発見できていない他の会社は、我々が壊れていると知っている状態のアップデートを受け取っていた。会社にとっても悲惨だし、会社の顧客にとってはもっと悲惨だ。

さらに、全社に向けて、そのようなパッチの内容を知らされないまま、ソースコードリリースも提供されていた。そのために我々は、コード変換器と呼ばれるものをビルドステップに挟んでいた。これはコード全体にわたって、一部のCプリプロセッサーシンボルを展開するので、#ifdef(COMS)とか#ifdef(LINKSYS)といったものが、消されるようになっていた。これにより、全社とも、それぞれ異なったソースコードリリースを受け取ることになっていた。顧客会社に渡すコードは、それぞれ別々にコンパイルした変換済みのコードであった。

さらに、それぞれの会社が独自に開発者を雇って、独自拡張を施しているし、彼らは我々のブランドではなく、製品を"Cisco"とか"Linksys"とかのブランドで出荷したがっていた。そのため、著作権表記とかを全部書き換えた以外は同一内容のソースコードを、単に顧客会社が全部自前で書いたように見せかけるために作っていた。

もう俺は足を洗って業界から身を引いたよ。

I hear you. It's so much worse than you can imagine. By the time the code g... | Hacker News

読者はこのような悲惨極まりない環境で開発されたハードとOSの利用を拒否せずんばあらざるなり。もはや自由不自由という問題ではなく、根本的にハナがヒン曲がるほどの腐臭を放つほど腐っているのだ。腐りきっているのだ。クソなのだ。クソすぎるのだ。この世の中にこのようなもはやこれを罵るに適切な罵倒言葉がまだ発明されていないが、その何かであるほどに悲惨なものが、存在を許されて言い訳がない。この腐った業界もろとも滅びるがよい。

仮想環境越しにCubase 5を動かす

Running Cubase 5 in a virtual machine (vmware) - YouTube

Cubaseというプロプライエタリな音楽作成用のUSB接続のデバイスとその操作用のこれまた不自由なソフトウェアを、仮想環境上で動かしたWindows XPから扱うデモ。

仮想環境であることによるオーバーヘッドは、リソースを富豪的に使うことにより解決できると豪語している。その物言いがあまりにもおもしろかったので紹介。

この動画では、VM内でCubaseを使っている。今日の強力なコンピューターをもってすれば、外部USBサウンドカードを、仮想環境に接続することは可能なのだ。たとえ、たとえ、ホストOSがLinux[訳注:Linuxとは単なるカーネルであり文意不通。おそらくはGNU/Linuxのことであろう]や、Macであったとしてもだ。VMに複数のコアを割り当てることができるので、CPU性能は問題にはなり得ない。

もし君が、そうだな、8コアCPUと大量のRAMを持ってるのならば、まともなパフォーマンスを得るために、5コア程度と数GBのRAMをVMに割り当てるぐらいのことは、当然やるだろ?

[訳注:仮想環境が] USBサポートをしてくれたおかげで、ネイティブシステム並みのレイテンシーが得られるぜ。

もう、HDDにCubase用のパーティションをこしらえる必要はなくなるのだ。

[訳注:Cubaseの不自由なソフトウェアは、Windowsのような不自由な上に使いづらいOS上でしか動かないので、GNU/LinuxやGNU Hurdのような、まともなOSを利用する者は、わざわざCubase操作用にパーティションを区切って醜悪なWindowsを入れなければならない]

なんとも富豪的発想だ。

2014-03-15

MozillaがMetro版Firefox開発中止を発表

Update on Metro | Future Releases

今週のはじめ、筆者はリードエンジニアとリリースマネージャーに、Windows Metro版のFirefoxの開発中止を指示した。開発チームはよくやってくれたが、Metroプラットフォームを取り巻く環境を考慮すると、1.0をリリースするのは、間違いだった。

Mozillaは世界をより良くするためにソフトウェアを開発している。しかし、我々は戦いを選ばねばならない。今や我々は、Firefox 1.0をリリースした時ほどちっぽけな存在ではないが、我々の労力は、我々が誓った目標を達成するために、集中して振り向けねばならない。我々の競合相手の強大さと、労力の多大さにより、我々は労力を適切に集中させなければならないのだ。

2012年末、筆者がMetro用Firefox開発チームを立ち上げた時(もうMicrosoftは、Metroという名称を使っていないが、我々内部で話すときは、未だにその名前を使っている)、MetroはWebの次の戦場のように思えた。Windowsは巨大な環境であり、Microsoftはこの新しいプラットフォームを強烈に打ち出していた。当初、我々は完全に閉めだされているようであった。我々はなんとかMetroをオープンにして、(ARMベースのRTは未だに閉鎖的だが)、開発を始めた。

何ヶ月もたち、開発チームが開発し、テストし、製品としての完成度を高めていくと同時に、我々はMetroの受け入れ具合を観察していた。見る限り、シェア率増加は完全に水平線である。例えばだ。毎日、何百万人もの人間が、リリース前のデスクトップ版Firefoxをテストしている。しかし、Metro環境の活発な利用者は、一日1000人程度しかいなかった。

これにより、我々は厳しい選択に迫られた。リリースすることはできるが、現実の環境であまりテストされていないものを表に出すことになる。つまり、現実に使われるようになると、多くのバグが発見されるだろうということで、多くの後出しの開発や設計やQAテストの労力がかかる。リリースして後出しの作業をしないという選択肢は存在しない。製品をリリースしたのならば、一生サポートし続ける必要があるのだ。戦いを選ぶという観点から言えば、これは割り合わない戦いだ。労多くして益少なし。

だから、引き上げることにした。これは、Metroが明日にでもおおはやりして、我々は急いで追いつかなければならないリスクを抱えることにはなるが、今現在、利用者が全く受け入れ姿勢を示していないプラットフォームに多大な投資を行うことを考えると、取るべきリスクだ。コードは残る。市場規模はともかく、我々はこの製品に多大な投資をしたと感じているが、しかし、より多くの人々に届く場に労力を集中する。まだこのコードにやるべきことはたくさん残っている。

Johnathan Nightingale, VP Firefox

Metroという不自由極まりない閉鎖的、制限的な環境で動くソフトウェア、いや、WindowsというプロプライエタリなOS用の自由なソフトウェアを開発するのは、本来不毛である。しかし、そのことによって、少しでも多くの人々が、不自由な肝教で動く自由ソフトウェアではあるが、自由のよさを認識してくれれば、完全に不毛というわけではない。

筆者は早く皆が自由の価値に目覚めることを願ってやまない。

2014-03-14

2014-01-pre-Issaquah mailingのレビュー: N3880-N3889

[なかなか悪くないHTML] N3880: Improving the Verification of C++ Programs

ようやく、C++論文で許せるマークアップのHTMLを読んだ気がする。

この論文は、C++にプログラムの検証を支援するための機能の必要性を提案している。

プロジェクトを始めるにあたって、どのプログラミング言語を選ぶかということは重要である。プログラミング言語ごとに利点や欠点があるので、考慮される。考慮に上がる対象に、検証可能性は重い。標準規格に、検証のための標準の規格がないのは、C++の利用を妨げる要因となっている。

この論文は、検証を標準規格でサポートするための必要性を提起するものであり、具体的な新機能の提案は含まれていない。ただし、現在のC++で改良できる分野として、いくつかの点を上げている。

たとえば、static_assertのメッセージを改良するだとか、API設計の妥当性を検証するためにコンパイルエラー自体をテストする機能であるとか、ill-formedの詳細な分類とか、文脈に依存したソースコード上の情報を取得する機能(リフレクションなど)や、より高度なassertionライブラリ、テストの際にのみ実行されるコード片の登録機能、検証プログラムの自動生成、などを挙げている。

まだ、検証力の必要性の提起だけなので、具体的にどのような新機能が提案されるのか、また実装可能なのか、興味深くはある。

[PDFも修正されるべき] N3881: Fixing the specification of universal-character-names

UCNに関する訂正。

C++11では、Unicode文字はすべてPhase of Translationのできる限り早い段階でUCNに変換するなどという定義にしてしまったため、真面目に実装しようとすると、色々と問題が出てくる箇所がある。また、変換前のソースコードを再び読まなければならない時もある。未定義な挙動もある。

そのため、いままで規格がカバーしきれていなかった範囲の挙動まで詳細に指定する文面の変更を行う提案。

具体的にどのような問題があるかは、論文を参照。

[PDFも使いづらいという現状を認識すべき] N3882: An update to the preprocessor specification

これもN3881と似通った論文。

忌まわしき太古の遺物であるCプリプロセッサーには、未定義な挙動が多々ある。当時としては、実装の自由度を持たせるために適切であったことも、Cプリプロセッサーが十分に枯れ尽くした今となっては、異なる実装間の移植性を妨げるだけである。

それに、今の最新のコンパイラー(GCC 4.9, Clang 3.4, 不自由なMSVC 12, 不自由なEDG/ICC 13)を比較すれば、もはや挙動の差異は微々たるものである。

そこで、今までCプリプロセッサーで未定義の挙動とされていた部分を、今の有名な実装の挙動を追認する形で、規格で詳細に定義する提案。

具体的にどのような問題があるかは、論文を参照。No! You cant haz cheeze burger!

N3883: Code checkers & generators

コードチェッカーとジェネレーターというか、コンパイル時リフレクション機能の提案。

この論文が大雑把に提案している機能は、コンパイル時に、コンパイラーのASTの一部をC++ユーザーに提供し、また生成する力を与えようというものである。

例えば、以下のようなクラスがあったとする。

// 人を表現するクラス
class Person
{
private :
    std::string name ;
    std::string address ;
    double weight ;

    // その他多くのデータメンバー

public :
    // 比較関数の宣言
    bool operator == ( Person const & rhs ) const ;
} ;

このクラスのoperator ==を実装したい。3個のデータメンバーがすべて等しければ等しいとみなすようにしよう。これは、以下のように書ける。

// 比較関数の定義
bool Person::operator == ( Person const & rhs ) const
{
    return  this->name == rhs.name &&
            this->age == rhs.age &&
            this->weight == rhs.weight &&
            // その他のデータメンバーの比較
            ;
}

しかし、このようなコードを手書きするのは、間違いの元である。もしPersonの宣言を変更した場合、operator ==も変更しなければならない。またまた間違いの元である。このような機械的なコードは、自動生成したい。

それには、コンパイル時にクラスのメンバーという情報を取得し、また取得した情報に基づいてコードを生成する力が必要だ。すなわち、ASTの取得と改変能力が必要だ。

N3883提案は、そのような強力な力をC++に与える力強い提案である。


// ドライバー
class EqualityDriver
{
    constexpr EqualityDriver(const ClassDecl & classDecl)
    {
        class_name = classDecl.getTypeName() ;
        for ( auto & field : classDecl.fields( ) )
        {
            members.emplace_back( field.getName( ) );
        }
    }

    meta::vector<meta::id_name> members;
    meta::type_name class_name;
} ;

// 比較関数生成のためのパターン
$define OperatorEqGenerator( EqualityDriver driver )
{
  bool $driver.class_name::operator==(const $driver.class_name & rhs) const
  {
    return true
      $for (auto member : driver.members) {
        && $member == rhs.$member
      }
    ;
  }
}

// 比較関数の生成
$OperatorEqGenerator( Person ) ;

N3883提案は、$define, $use, $for, $if, $switchという新しいキーワードで、ASTを取得、あるいは改変する。

一度このような生成規則を書いてしまえば、あとは、全データメンバーを比較するあらゆるクラスに適用できる。


struct Foo
{
    int x ;
    int y ;
    bool operator == ( Foo const & ) const ;
} ;

struct Bar
{
    double d ;
    bool b ;
    bool operator == ( Bar const & ) const ;
} ;

$OperatorEqGenerator( Foo ) ;
$OperatorEqGenerator( Bar ) ;

いや、ちょっと待て。先ほどのクラスPersonだが、weightというデータメンバーの値は、比較の対象にならないようにできないのか。第一、人は体重が増減しても、同一人物ではないか。

もちろんできる。

// 体重を考慮しないドライバー
class EqualityDriver
{
    constexpr EqualityDriver( const ClassDecl & classDecl )
    {
        class_name = classDecl.getTypeName();
        for ( auto & field : classDecl.fields() )
        {
            // 特定の名前のデータメンバーをフィルターする
            if ( field.getName() == "weight" )
                continue ;

            // 残りは追加。
            members.emplace_back(field.getName());
        }
    }
    meta::vector<meta::id_name> members;
    meta::type_name class_name;
} ;

これぐらいたやすいことだ。そう、N3883提案ならば、C++はASTの一部に干渉できるのだ。

他にも、具体的なコード例は省略するが、構造体の配列を、構造体の各データメンバーの配列に変換したり、既存の関数を置き換えたり、文字列からenum型を生成したりと、やりたい放題だ。

そう、もはやCプリプロセッサーマクロは時代遅れの遺物になるのだ。これから#defineなどと書く幽霊プログラマーは、後ろ指をさされてひと目を忍んで地下に潜って、かつての混沌とした日々を懐かしむぐらいしかすることがなくなるであろう。$if, $else, $switchにより、従来のCプリプロセッサーマクロの役割は、完全に代替される。

そう、テンプレートメタプログラミングも時代遅れの遺物になる。もはやTMPでレイトレーシングをする岡山の陶芸家はお呼びではないのだ。

コンセプトですら、N3883により、改善される。

この提案は、AngularJSから影響を受けており、またその設計には、Clang APIをそのまま持ってきている。

唯一の不満点は、その文法が悲惨なことだ。$はPHPを彷彿とさせるものがある。

文法に議論の余地はあるものの、このような提案は、さらに発展させるべきだ。

[PDFも一新されるべき] N3884: Contiguous Iterators: A Refinement of Random Access Iterators

Contiguous Iteratorという概念を標準ライブラリに追加する提案。

Contiguous Iteratorとは、連続したストレージ上に確保されている要素の集合を指し示すイテレーターであることを保証するものである。

つまり、以下のようなことが保証される。

// Contiguous Iteratorの例
template < typename contiguous_iterator >
void f( contiguous_iterator iter )
{
    auto next = iter + 1 ;
    &*iter + 1 == &*next ; // true
} 

つまり、イテレーターの指し示すオブジェクトのポインターを+1した結果のポインターと、イテレーターを+1した結果のイテレーターの指ししめすオブジェクトのポインターが、等しいことが保証される。

これは、たとえばC時代のAPIにポインターを渡すとか、連続したメモリであることを検出してmemcpyに切り替えるなどのアルゴリズムの最適化など、連続したストレージ上に確保されていることが保証されていることを利用したコードが書けることを意味する。

[PDFを廃止する提案] N3886: A Proposal to add a Database Access Layer to the Standard Library

データベースアクセスのためのインターフェース的なライブラリを標準ライブラリに追加する提案。

論文には、具体的なインターフェースの設計が書かれているので、興味のある人は呼んでもらいたい。このブログにコピペして解説することはしない。

インターフェースの設計は、バックエンドのデータベースとして、SQLベースのリレーショナルデータベースを想定している。

このような共通のインターフェースを標準化する理由としては、データベースアクセスのためのAPIは、実に多数あり、しかもその多くが、大昔のCの設計になっている。モダンなC++風の洗練されたインターフェース設計のライブラリが存在するべきである。

[一貫性のために論文フォーマットとしてPDFを廃止せよ] N3887: Consistent Metafunction Aliases

[PDF注意] N3655で、ほとんどのメタ関数には、エイリアステンプレートを用いて、metafunction_tが作られたが、tuple_elementだけは欠けていた。そのため、tuple_element_tを付け加える提案。

また、すべてのメタ関数にそのようなエイリアスが必要というわけではない。そのようなエイリアスが必要もないメタ関数だってある。そのため、いつ_tにすべきかという今のガイドラインは、あまりにも範囲が広すぎるという議論もしている。

[PDFで公開するようでは、お先真っ暗] N3888: A Proposal to Add 2D Graphics Rendering and Display to C++

2Dグラフィック描画ライブラリをC++に付け加える提案。

なぜ必要なのかという理由から始まって、グラフィック関連の様々な事情を説明している、結構長い論文。これはいずれ、別の記事で詳しく紹介したい。

今の予定では、土台としてcairoを用い、C言語によるインターフェースに、機械的な変換ルールを定義して、C++風のインターフェースに書き換えるようにしている。

その変換ルールも提案している。

[高濃度のPDF汚染を検出] N3889: Concepts Lite Specification

Concept Liteの仕様書案

ドワンゴ広告

この記事は、ドワンゴに昼過ぎに出社してボードゲームをやる合間に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

最近のUbuntuの動向

先月、色々と忙しくて観測対象から外れていたUbuntuの動向をまとめた。

[Phoronix] Ubuntu To Abandon Upstart, Switch To Systemd

Ubuntuが、将来的にUpstartからSystemdに移行する意向を発表した。

[Phoronix] Ubuntu Systemd Plans: Will Be Default By Ubuntu 16.04 LTS

Systemdは、Ubuntu 16.04 LTSにはデフォルトになるという計画が発表された。

[Phoronix] Shuttleworth On Google Go, Unity 8, Ubuntu Phone, Etc

また、開発者サミットでShuttleworthが発表した内容によると、Mirは16.04 LTSでデフォルトになる予定だそうだ。Canonical内部ではGoが使われているそうだ。

2014-03-13

ValveがOpenGLデバッガー、VOGLを公開した

GNU/Linuxに不自由なソフトウェアを蔓延させる目的で活動してるValveが、VOGLという自社製のGNU/Linux上で動くOepnGLのデバッガーをGitHubで公開した

ValveSoftware/vogl

まだ開発段階で、ろくにドキュメントもないようだ。早期に公開するという姿勢は評価したい。残念ながら、彼らのソフトウェア流通プラットフォームは邪悪のDRMがかかった不自由ソフトウェアを蔓延させるものなのだが。

最近このブログがつまらなくなったという指摘について

最近、このブログがつまらなくなったという意見を聞いた。実際、この二ヶ月、色々とあってブログの執筆は、いつもより少なかった。

これは一時的なもので、その理由は、環境の変化だ。

1月中旬に、私は京都から東京に引っ越さなければならなかった。引越というのは結構面倒な作業なので、まずその作業に時間を取られていた。

さて、東京に着いたあとも、住んでいる家の整備で色々と時間を取られていた。シェアハウスに住んでいるから、まだこの程度ですんでいるが、これが完全に一から環境構築となると、途方もない作業が必要になる。

ようやく、妖怪ハウスのネット環境は整えたものの、まだ色々と、自宅は作業をする環境になっていない。

まず、自宅にはまともな椅子がないし、まともなディスプレイもない。椅子とディスプレイは慎重に選ぶべきものであるし、いいものは高いので、まだ購入していない。

それから、自宅の押入れを何とかしなければならない。とりあえず、私の荷物を入れるスペースとして、押入れの上の段を確保したのだが、この押し入れは、垂直方向に高いので、空間を効率的に活用するためには、何らかの仕切りが必要になる。その仕切りをどのように作成するかが、目下の問題だ。

押入れの大きさは、高さ80cm、奥行き80cm、幅160cmといったところだ。高さはもっとあるのだが、上30cmほどは、押入れ自体に棚がついている。

しかし、高さ80cmというのは、まだ高すぎる。これを二つか三つほどに区切って、垂直方向に空間を活用したい。

最初考えたのは、押入れにはまる大きさの本棚を押し込んでしまうことだ。しかし、それではあまりに仕切りが細かすぎる。

あるいは、ラックを入れるという手もある。しかし、ラックの価格を調べた所、押入れをラックで満たすには、3万円はかかる計算になる。

引き戸式の収納ケースのようなものを積み重ねるという案もある。しかし、やはりこれも、押入れを収納ケースで満たすには、数万円はかかるだろう。

金はないこともないが、そんなに大金を使いたくない。もっとハックして安く上げたい。

資材屋で角材と板を買ってきて自作するという手もある。これは、材料費ならば5千円もあればできるはずだが、はたして十分な強度と仕上がりになるだろうか。

とにかく、自宅の環境を整えないことには、自宅でブログ執筆ができない。

では、会社ではどうか。会社ではブログ執筆ができる環境が整っている。しかし、誘惑も多い。ボードゲームというとても抗いがたい誘惑がある。

しかし、ボードゲームは一日にせいぜい1,2時間ほどだ。残りの時間は何をしているのかというと、今は論文のレビューをしている。

大半の読者は、私の通常の記事を期待しているのかも知れないが、私はC++ Evangelistである。C++の啓蒙家を名乗る以上、最新の論文にはすべて目を通し、解説しなければならない。また、ドワンゴでは、提案されている新機能に対し、現場の意見を聞くことができるので、極めて規格と論文のレビューに素晴らしい環境となっている。

そうなると、必然的に、いつもより解説に力が入る。解説に力を入れるということは、時間がかかるということだ。いつもなら、「簡易レビュー」という名前で、論文の概要程度の解説だったのだが、今回は、詳細にまで踏み込んだ解説をしている。これにはかなり時間がかかるが、その代わり、記事の質は大幅に向上している。

引越と環境構築に時間を取られたのと、いつもより詳細に解説していることにより、論文一本一本の解説の執筆に時間がかかり、そのために、他の雑学的なブログ記事の執筆は、現在、あまり行っていない。しかも、post-Issaquah mailingまで公開されているので、この状態はしばらく続く。

C++以外の記事を期待している読者もいるかもしれないが、やはり私は、C++啓蒙家なので、ここはおろそかにはできないのだ。

取り急ぎ、雑学的なブログ記事を読みたい人は、Amazon.co.jp: 江添亮: 江添のほしい物リストで何かを買って妖怪ハウスに送れば、まとまった量の商品が届いた時に、その商品について何かを書くつもりだ。もし、アマゾンを経由しないで直接送りたい場合は、以下の住所に送ってもらいたい。

筆者にブログのネタになる品物を直接送りたい場合の宛先:
郵便番号:165-0027
住所:東京都中野区野方5-30-13 ヴィラアテネ401
宛名:江添亮

その他の英語圏のニュースの紹介などの記事は、恒例のC++WGの論文のレビューは片付くまでは、しばらくは数が少なくなるだろう。

妖怪ハウスのネット環境改善作業

筆者が妖怪ハウスにやってきたとき、妖怪ハウスのネット環境は悲惨だった。

まず、ISP提供のモデム兼ルーターと、無線LANルーターが床に落ちている。配線も他の様々なコードとからみあって、わけがわからない状態であった。5LDKの家でLANケーブルが床を無造作にはっている。

そして、無線LANルーターが貧弱すぎて遅かったし、すぐに途切れた。有線でもやはり遅かったし、時々動かなくなることが会った。

住人の話では、「夜に特に遅くなる。0.01Mbpsしかでないときもある。誰かがP2P型のファイル共有かなにかで帯域を使っているのだろうか」ということであった。

そもそも、ISPとの契約書すらなくしていた。一体、回線がどういう契約なのかすらわからない。VDSLだろうか。光ファイバーが来ているのだろうか。それを調べようにも、機器が床に落ちて、複雑に絡み合ったコードの中に埋まり、確認ができなかった。

色々と調べた結果、回線はフレッツ光だった。いくら住人と客人で使うからと言って、200Mbpsもあれば十分なはずだ。なぜこんなに遅いのか。

その帯域というのも、それほど狭くはない。試してみれば、100Mbps以上は余裕で出る。問題は、帯域は広いのだが、なぜか帯域を観測すると波がある。数秒100Mbps以上でて、数秒落ち込むというサイクルを繰り返している。

それに、この家の住人で、P2P型ファイル共有ソフトウェアを使えるだけの十分な知識を持っていそうな人間は数人しかいない。プライベートネットワーク内におけるファイル共有はかなり発見できるが、これは、不自由なWindowsや不自由なMac OS Xがデフォルトで設定しているものにすぎない。それに、これは1Gbpsのプライベートネットワーク内で完結しているものであり、インターネット上には出て行かない。

まてよ・・・ひょっとしてルーターのせいなのだろうか。考えてみれば、ISP提供のルーターは、このようなシェアハウスの環境を想定していない。何人も住んでいて、客人も来て、それぞれに数台はコンピューターを使っていることを考えれば、ISP提供の非力なルーターが耐えられるわけがない。

それにしても、なぜこんな環境で、住人は暮らせているのだろうか。インターネットは、もはや水や電気と同じく、基本的人権に加えられるべきインフラだ。こんなに貧弱なネット環境はありえない。

仕方がないので、筆者自ら、妖怪ハウスのネット環境を強力に作り変えることにした。ルーターが確認できないほどこんがらがった電源ケーブル、LANケーブルを整理し、各部屋に送るLANケーブルも壁に固定しなければならない。また強力なネットワーク機器が必要だ。

筆者は秋葉原に行き、様々な機器を購入した。だいぶ痛い出費だったが、仕方がない。

まず、電源ケーブルを整理した。複数の電源タップに、テレビやルーター機器などの抜いてはいけないコンセントと、抜いてもいいACアダプターなどが、乱雑にささって、ゴルディアスの結び目よろしく、複雑に絡み合っている。残念ながら、ここではかの大王が取ったような画期的な手法を取ることはできない。一つ一つ結び目を解いていかなければならないのだ。

そもそも、なぜISPレンタルルーターと、無線LANルーターが、床に落ちて電源ケーブル類と絡まっているかというと、Ethernetポートのためだ。ISPレンタルモデムと無線LANルーターのポートすべてに、LANケーブルが刺さっている。元は本棚の上に設置していたそうだが、ケーブルに引っ張られて床に落ちたまま、放置されていたのだ。

Ethernetポートが足りないから、こういうことが起こるのだ。ポートがルーターにしかないから、そこに刺してしまうのだ。この問題を解決するためには、ポート数の多いスイッチングハブを使い、ルーターからケーブルを取り除く必要がある。たまたま、同居人が5ポートほどあるBUFFALOのハブを持っていたが、これをネットワークに接続すると、なぜか家中のネットワーク全体が不安定になる。壊れているのだろうか。

秋葉原で色々と探した挙句、筆者はNETGEAR GS116v2 16ポート ギガビットノンインテリジェントスイッチ (省電力製品) GS116-200JPS (本体ライフタイム保証)日本電気 AtermWG600HP PA-WG600HPを買った。

特に選択に意味はない。BUFFALOという安かろう悪かろうの粗悪な製品を避けたかったからだ。

さて、もともと、ルーターからLANケーブルを排除する目的で、Netgearの16ポートのスイッチングハブを導入し、ISPレンタルルーターへの接続を一本にしたところ、なんと、ネットワークの不安定さが、だいぶ解消されてしまった。なるほど、ISPレンタルの貧弱ルーターのEthernetポートをすべて埋めると、負荷がかかりすぎてしまうのかもしれない。それにしても、スイッチングハブというのは、実は意外と高度なことをしているのだな。いままで、スイッチングハブの存在を侮っていた。単にLANケーブルを分割する程度の認識しか持っていなかった。今回買った、このNetgearの製品は、ノンインテ入りジェントという名称が入っているが、どうやらこれは、同社の他の製品に比べればノンインテリジェントという意味らしい。さらに高価なスイッチングハブには、ハブ自体にQoS機能などがあり、ハブにログインして設定できるのだという。

さて、そして、今までの56Mbpsでしかリンクできない貧弱なBaffaloNECの無線LANルーターを、NECのルーターで置き換えた、このNECのルーターの設定UIはとてもクソで、初回ログインはクソみたいなわけのわからない、しかもまともに設定できずに使い物にならない、そもそもまともに設定して突破することもできない、自称簡単設定UIを表示し、しかもその設定を済ませなければ詳細な設定UIにアクセスできないとあって、非常に難渋した。幸い、このNECのクソUIのルーターに詳しい知人が、一度ログインしたまま、もう一度ログインすると、通常の詳細設定UIが表示されるという助言をもらったので、なんとか、この自称簡単設定UIを突破することができた。いったい何なのだ、このクソUIは。

しかも、詳細設定のUIも、設定の保存と設定の摘要が分かれているという、これまた訳のわからないクソUIだった。いったい、どこのバカがこんなクソUIを設計したのだ。

さて、NECのルーターのUIは、本当に本当にとてもとても排泄物だった。最初、設定のために、ルーターモードにしたNECのAtermとコンピューターをLANケーブルでつないで、ルーターにログインし、望みどおりに設定してからアクセスポイントモードにして、そのあとに妖怪ハウスのネットワークに接続した。すると、なぜか設定が反映されていない。いったいこれはどういうことだ。再びルーターモードに戻すが、やはり設定されている。APモードにすると設定されない。もしやこれは・・・

なんと、このNECのクソ無線LANルーターは、ルーターモードとAPモードで、設定が独立しているのであった。いったいどこのトチ狂ったバカが、どんな薬物を摂取したら、こんな設計になるのだ。根本的に腐っている。

さて、設定に関して、とても糞だったNECの無線LANルーターだが、とりあえず無線LANとしては、そこそこの仕事をしてくれた。ただし、いずれは業務用のいい無線LAN APを導入したい。

さて、Netgearのスイッチングハブと、NECの無線LANルーター(APモード)を導入したところ、妖怪ハウスのネット環境は、なんとかなりマシになってしまった。なるほど、スイッチングハブは侮れないのだな。そして、無線LANも、安物を使うべきではないのだな。

しかし、まだダメだ。まだ満足できない。まだ遅い。どうも、DNS検索が遅いように思う。このISPレンタルルーターがDNSキャッシュサーバーとして動いているようだが、遅すぎてキャッシュの役割を果たしていない。むしろ逆に遅くなっている。そして、TCPコネクションを張るのにも、やや時間がかかっているように思われる。やはり、根本的に、このISPレンタルルーターは非力なのだ。DNSサーバーはこちらで設定することもできるが、住人全てにその設定ができるわけではない。

やはりここは、強力なルーターを導入しなければならない。100台規模の機器を余裕でさばけるような強力なルーターがほしい。しかし、そのような強力なルーターはなかなかに高価だ。さてどうしよう。

なんと、そのルーターが無料で手に入った。なんとも親切な人が、余っているからと、新品同様の YAMAHAのRTX810を送ってくれたのだ。RTX810だと。それはちょっとした中小企業に導入して会社内のネットワークをそれひとつでさばけるような強力なルーターではないのか。そんないいものを。

さて、どうやってこのルーターを導入すればいいのだろうか。ISPレンタルルーターをよく観察したところ、どうやら、モデムとルーターの一体型に思われたこの機器は、内部で二つに分かれているようだ。モデム部分からUNIという名称でEthernetポートがあり、そこにルーター部分からLANケーブルがつながっている。これを差し替えれば、ISPレンタルの貧弱ルーターを使わないということが可能だ。

ただし問題は、電話が使えなくなるということだ。ある住人は、仕事上、自宅にFAXを置かなければならないため、難しい問題だ。なぜFAXを必要とするかというと、旧態依然の保守的でクソみたいな裁判所が、いまだにFAXを使い続けるからだ。日本の裁判所は、FAXのような平文で送信する信頼できない通信方法ではなく、電子署名と暗号化による暗号理論的に適切な通信方法に、今すぐ移行しなければならない。すでに行政の多くは、移行している。裁判所がそれをしないのは甚だしい怠慢である。

さて、それはともかく、せっかくYAMAHAのRTX810があるのだから、試験的に導入を試みた。これが・・・なかなか難渋した。

RTX810は、HTTPサーバーとして機能して、ブラウザー上から操作する簡単なUIを提供している。このUIは、NECのクソUIよりは、いくらかマシであったが、やはり使いづらい。

RTX810は、telnet/ssh/シリアルポートから接続して、直接文字列でコマンドを送信することで、設定することもできる。ただし、これがあまりよろしくない。

まず、まともなシェルがない。そして、文字コードが忌々しきシフトJISである。しかも、勝手に行数を区切って--more--的な表示をする(ただし、シフトJISで日本語なので、よくわからない)

わざわざシフトJISロケールを生成して、ターミナルからシフトJISを扱うのも面倒だ。とりあえずteeコマンドでファイルに吐き出してみたが、ド素人丸出しである。iconvで変換すればいいのではないかとおもったが、どうやらiconvは入力をバッファしてしまうらしく、動かない。入力をバッファせずに文字コード変換を行うソフトウェアに、nkf -uがある。これでようやく、出力の意味がわかった。しかし、なぜ日本語なのだ。なぜシフトJISなのだ。YAMAHAの顧客は不自由なWindows利用者だけなのか。どんなに小規模なネットワークであっても、管理者がWindows利用者というのは考えられないのだが。

あとで知ったことだが、RTX810では、以下のコマンドを使うと、まともな出力になるということが判明した。これがデフォルトになっているべきである。


console character ascii
console columns 200
console lines infinity

忘れずにsaveしておこう。

さて、設定は終わり、実際にISPレンタル機器のUNIに接続してみたが、どうも動かない。いや、厳密に言うと動く。ISPとのPPPoEは通り、もちろんインターネットにつながっているのだが、なぜかDNSの設定がうまくいっていないようだ。それも、DHCPでDNSサーバーのIPアドレスを通知するところがうまくいっていない。なぜだろうか。

この問題は、ついに、なぜ動かなかったのかわからなかった。何度か試行錯誤するうちに、いつのまにか動くようになった。おそらく、最初はadministratorコマンドをうち忘れていたのではないかと思う。

さて、RTX810の初期設定では、DHCPで割り当てるIPアドレスは、192.168.100.xとなっている。住人の中に、わかりにくいから192.168.1.xから割り当ててくれと言う人間がいたので、dhcp scopeを設定した。設定したところ、どうやら間違えてしまったようで、RTX810のDHCP機能が動かなくなってしまった。dhcp scopeの設定方法を、もう少し学ばなければならない。第一、ネットマスクなる用語の意味を、正確に把握していない。

DHCPが動かないだけなのだから、DHCPにたよらずに、自前でIPアドレスを主張すればよかったのだが、早急に復旧させる必要があるため、そこには思い至らなかった。

RTX810は、RS-232cポートを持っており、シリアルケーブルで接続することでログインすることもできる。あいにくと、私のラップトップに、そのような古典的なポートは存在しない。今や、シリアルポートといえばUSBやSATAのたぐいを言うのであって、RS-232cではない。住人の一人に、シリアルポートのついた昔のラップトップを所有している人がいたが、残念ながら、ケーブルがない。

しかたがないので、スイッチの同時押しで、RTX810を初期化した。

初期化後、再び一から設定を始めたが、もうすっかり慣れたと見えて、こんどは短時間で設定できた。

ただし、初期化したことは正解であった。RTX810を譲ってくれた人を疑うわけではないが、やはり念の為に、初期化をしておくべきだろう。

さて、RTX810を試験的に導入した結果だが、完全に世界が変わった。ネットワーク内の遅延が劇的に改善され、実に快適で強力なネット環境が構築された。いつか人を集めて、各人ごとに持てるだけのコンピューターを持ってきてもらい、妖怪ハウスネット環境のストレステストを行いたいものだ。ただし、それには、もっと強力な業務用の無線LAN APも必要となるだろう。

なるほど、ネットワークの構築作業というのは、意外と楽しい。ハードウェアや構成を変更すると、パフォーマンスが劇的に変わるというのは、とても楽しい。いままで、ネットワーク管理者というのは、つまらなそうな職業だと思っていたが、なかなかどうして、やりがいのある仕事だ。いままであまりよろしくなかったネットワークのパフォーマンスを大幅に向上させた時の快感はたまらないものがある。自宅で中小企業に入れるレベルの機器を使って、数十台規模のネットワークを構築できる経験ができるというのは恵まれているといえるだろう。

とりあえず、今はISP提供のレンタルルーターを使っている。住人にFAXを使う人がいる以上、難しい問題だ。ネットワークに負荷がかかると予想されるとき(客を大勢呼んだ時とか)に、RTX810に差し替えるつもりだ。ただし、いずれは、RTX810に置き換えたい。

電話の問題は、二回線引けばいいのだが、残念ながら、その住人にはそれほど金がない。ただし、裁判所がセキュリティ的にどうしようもないFAXを使い続ける以上、やはり専用の線をひくべきではあるのだが。いや、むしろまともな暗号理論の知識がない裁判所が変わるべきなのだ。裁判所、お前はクソだから改善しろ。数学的に証明された手法を否定して、平文で送る(しかも受け取り側の電話というのは、普通は人が張り付いておらず放置されているので、誰に読まれるかわからない)クソみたいなセキュリティがザルのFAXを、即刻廃止しろ。裁判所はクソだ。

妖怪ハウスの配線とネット環境は改善された。もうLANケーブルが床をはうことはない。もう貧弱な無線LANに悩まされることはない。トイレの中にまで無線LANが届くので、トイレにも作業用に電源タップを配置した。

まだ妖怪ハウスに改善すべきところは多々あるが、また後ほど、改善作業を終わらせてから記事を書く。

他にも欲しい、高価なネットワーク機器はある。またそれ以外にも欲しいものがある。レトロゲームのソフトや本体や周辺機器を揃えたい。これらは不自由なコンピューターではあるが、どうしても昔の思い出は捨てがたいのだ。現在、ファミコン、スーパーファミコン、ニンテンドー64、ゲームキューブ、PS2、PS3がある。ただし、PS2とPS3は新しすぎるのでレトロゲームの定義には当てはまらない。

もし、読者の中に、レトロゲームのソフトや周辺機器を妖怪ハウスに寄贈したい人がいれば、大歓迎だ。いつでもゲームをやりに遊びに来て欲しい。いまのところ、以下のものが欲しい。

ファミコン、スーパーファミコン、ニンテンドー64、ゲームキューブのソフト。クソゲーも歓迎する。スペランカーや元祖西遊記スーパーモンキー大冒険のような有名なクソゲーもある。また、ファミコンのディスクシステムもあるので、ディスクシステム用のソフトも欲しい。

スーパーファミコンのコントローラー(あと2本)とマルチタップ

ニンテンドー64のコントローラー(あと3本)、コントローラパック(いくつでも)

ゲームキューブのコントローラー(あと3本)、ゲームボーイプレイヤー(中古市場で手に入れるには、本体ごと購入する必要があり、高価)

ゲームボーイ、ゲームボーイポケット、ゲームボーイカラー、ゲームボーイアドバンスの本体と周辺機器とソフト(私が50分以内にRTAできるキャッスルヴァニア 〜暁月の円舞曲〜が特に欲しい。現在、中古市場価格が高止まりしていて、高価)

その他のレトロゲーム本体とソフト

2014-03-12

2014-01-pre-Issaquah mailingのレビュー: N3872-N3879

N3872: A Primer on Scheduling Fork-Join Parallelism with Work Stealing

これは提案ではなく、Fork-Joinにおける実装戦略の入門書的な論文。

Fork-Joinというのは、処理の単位を発生させて、ある地点で、発生させた処理が全て終わるまで待つものだ。Clik風の文法で書くと、以下のようになる。

// Clik風文法によるFork-Join
// オリジナルのスレッドが実行開始
e() ; // オリジナルのスレッドが逐次実行
spawn f() ; // 並行して実行される処理を生成
g() ; // fとは並行して実行される
sync ; // f, gの処理が両方終わるまで待つ
h() ; // 逐次実行

さて、ここで疑問が二つある。

  1. fとgを実行するスレッドは何か?
  2. hを実行するスレッドは何か?

fとgを実行するスレッドは何か?

Fork-Joinという概念による並列実行のスケジューラーの実装方法としては、Work-stealingというものがある。これは、MIT Cilk, Intel Clik Plus, Microsoft PPL, OpenMPで使われている。work stealingの概要としては、まずスレッドが処理を作る。スレッドが処理の実行を終えたら、そのスレッドは泥棒(thief)となり、別のスレッドで未実行のままたまっている処理を横取りする。

上の例では、spawn f() ; で処理が作成されている。さて、その処理を作成したオリジナルのスレッドは、fとgのどちらの実行をすればいいのだろうか。それには、ふたつの戦略がある。

  • Child Stealing: fは泥棒スレッドに盗まれるようにし、オリジナルのスレッドはgを実行する
  • Continuation Stealing: オリジナルのスレッドがfを実行する。オリジナルのスレッドの実行の継続は、別の泥棒スレッドに任せる。

これは、一見すると、些細な違いのように見える。しかし、ループの中で処理を延々と生成していくようなコードでは、この違いが問題になってくる。例えば以下のコード、

// 戦略の違いが問題となるコード
for ( int i = 0 ; i < n ; ++i )
{ spawn f( i ) ; }

sync ;

さて、このコードを実行すると、f(0)から、f(n-1)までの処理が生成される。ここで先ほどの二つの戦略を当てはめてみると。

Child Stealingでは、spawn f( i )を実行したあと、オリジナルのスレッドは、未実行の処理の数にむとんちゃくでfor文の実行を続けるので、f(i)が爆発的に生成されてしまう。これにより、未実行の処理を記録しておくリソースなどが浪費される。

Continuation Stealingでは、オリジナルのスレッドが、まずf(0)を実行しに行く。for文の実行は、泥棒スレッドに任せる。この戦略では、未実行の処理が爆発的にたまることはない。泥棒スレッドがあるだけ効率的に処理を生成し、実行できる。ただし問題は、本来実行していたスレッドとは別のスレッドが実行を継続することになるので、たとえばレジスターやTLSなど、退避、復帰させなければならないデータがたくさんあり、コストがかかる。

また、Child Stealingは、純粋にライブラリだけでも実装できる。Continuation Stealingは、コンパイラーのサポートが必要だ。

それに、Continuation Stealingは、一見逐次実行に見えるのに、実行するスレッドが変わるので、初心者を混乱させる。

hを実行するスレッドは何か?

さて、syncによってjoinしたあと、hを実行するスレッドは、いったいなんだろうか。これには二つの実装戦略がある。

  • Stalling: オリジナルのスレッドが実行する。
  • Greedy: 最後に処理を終えたスレッドが実行する

Stallingの、オリジナルのスレッドが実行を再開するのは、とてもわかりやすい。ただし、それはオリジナルのスレッドが、すべての処理が終わるまで待たなければならない。そのためにStallingと呼ばれている。うかつに時間のかかる処理を、オリジナルのスレッドが盗んでしまうと厄介だ。

Greedyは、最後に処理を終えたスレッドが実行するので、スレッドが何もしないで待つ必要がない。ただし、オリジナルのスレッドとは別のスレッドが実行を継続する可能性があるので、TLSなどがうまく動かないし、TLSもうまく動かすようにしようとすれば、相当のスレッド環境の退避、復帰のコストがかかる。それに、わかりにくい。

TBBとPPLはStallingをサポートしている。Cilkは、Greedyをサポートしているが、Stallingをサポートする実験的なライブラリもある。OpenMPは、なんとまた、どちらもサポートしている。

[汚らしいド素人の書いたHTML] N3873: Improved insertion interface for std::{unordered_,}map

論文のタイトルは"Improved insertion interface for unique-key maps", 論文のHTMLのtitle要素は、"Improved insertion interface for std::{unordered_,}map"という一貫性に欠けるマークアップ。しかも、物理的な改行が意味を持つコードをマークアップするのに、既存の意味的にもふさわしいpre要素やcode要素を使わずに、div.code { white-space : pre-wrap ; }しているという、汚らしいド素人が書いたであろうマークアップの論文。

mapとunordered_mapにemplaceのようなものを追加する提案。

既存のmapとunordered_mapのemplaceは、キーが存在する場合、要素の挿入を行わない。問題は、要素の挿入が行われなかったとしても、依然として、実引数で渡したオブジェクトは、ムーブ後の状態になる可能性がある。

// emplaceの例
std::map<std::string, std::unique_ptr<Foo>> m ;
m["foo"] ; // キー"foo"を挿入

std::unique_ptr<Foo> p(new Foo) ;
// キーはすでに存在する
// pはムーブ後の状態になっている可能性がある
auto res = m.emplace("foo", std::move(p)) ;

挿入を行わないのならば、ムーブしなくてもいいし、実際、そのように実装することもできる。ただし、規格は上の例で、pをムーブ後の状態にすることを禁止していないし、実際にムーブ後の状態にするライブラリ実装もある。なぜかというと、emplaceは、実引数から、std::pair< std::string, std::unique_ptr<Foo> >のオブジェクトを生成するのだが、この生成は、キーの検索の前に行われることが、規格上許されているからだ。規格上許されている以上、そのように実装しても何の問題もない。

そこで、キーが存在した場合は、実引数のオブジェクトに何の変更をもくわえないことを保証した、新しいメンバー関数、emplace_stableを追加する提案。

// emplace_stableの例
std::map<std::string, std::unique_ptr<Foo>> m ;
m["foo"] ; // キー"foo"を挿入

std::unique_ptr<Foo> p(new Foo) ;
// キーはすでに存在する
// pはムーブ後の状態になることはないことが保証されている
auto res = m.emplace_stable("foo", std::move(p)) ;

なぜ、既存のemplaceをemplace_stableの挙動にしないのかというと、どうも、うまい文面案が思いつかないらしい。なんともプラグイン的な解決方法だ。

提案では、もうひとつ、empalce_or_updateというメンバーを付け加える。これは、キーが存在する場合でも、上書きムーブする。


std::map<std::string, std::string> m ;
m["foo"] = "bar" ;

std::string value{ "hoge" } ;

// キーが存在するので上書きされることはない
m.emplace_stable( "foo", value ) ;
m["foo"] ; // "bar"

// キーが存在するが上書きする
m.emplace_or_update("foo", std::move(p)) ;
m["foo"] ; // "hoge"

emplace_or_updateは、emplace_stableがあれば、効率を落とさず簡単に実装できる。なぜならば、emplace_stableは、イテレーターと、挿入を行ったかどうかをpairで返すからだ。


auto it = m.emplace_stable("foo", std::move(p));
if (!it.second)
{
    it.first = std::move(p); 
}

とはいえ、こんなコードをいちいち書きたくない。標準ライブラリで提供されているべきだ。

[クソみたいなPDF] N3874: Light-Weight Execution Agents

スレッドとかタスクとかSIMDとかベクトル実行とか、様々な名称で呼ばれている、light-Weight Execution Agent(軽量実行物)の定義を与える提案。

Execution Agentとは、実行の単位の名称である。

C++11では、スレッドを導入し、C++に並列実行の道具を与えた。

Execution Agent(実行物)とは、すでに規格で定義されている用語(§30.2.5.1 paragraph 1)だ。スレッドは、「ブロックされていない限り、いずれ実行が進む」("should eventually make progress if they are not blocked.")と定義されている。これは、とても強い保証を持っている。

ところで、C++11で入ったスレッドというのは、たとえばPOSIXのpthreadをモデル化したものであり、多くの実装ではOSの提供するスレッドである。このようなスレッドは、とても重たい。しかし、そのような重たいものは、大量に生成すると、リソース使用量の点でコストがかかる。軽い並列処理には、もっと軽い単位のExecution Agentが使われるべきである。すでに、そのような提案はあるが、みな用語がバラバラである。その根底にある基本的なExecution Agentという概念を、共通化してまとめて定義しよう、と、こういう提案である。

まず、Foward progress(実行が進む)保証について考察する。これにはいくつかの保証の強弱が考えられる。

Concurrent execution
スレッドのような、いずれ実行が進むという強い保証
Parallel execution
スレッドプールやFork-joinのような、弱い保証。クリティカルセクションの使用にも難あり。
SIMD execution
SIMD演算のモデル化。これはやや特殊な保証。
Parallel+SIMD execution
ParallelとSIMDを組み合わせて、両方の良いとこどりをねらった保証。ただし、この保証の存在理由には疑問もある。

また、スレッドの紐付けられた状態という点からも考察できる。たとえば、TLSや、this_thread::get_id()や、ロック所有するスレッドという点だ。

論文は最後に、いくつかの疑問を提示している。

[おぞましいPDF] N3875: Run-time bound array data members

実行時にサイズを指定できる配列をクラスのデータメンバーとして持つことができるようにする提案。

ただし、Cとはだいぶ違う方向だ。そして、名前も、実行時サイズ配列(runtime sized array)ではない。

まず、文法をひと通り見ていくことにしよう。

// 文法例
struct runtime_size_bound_class
{
    char [] runtime_bound_array ;

    // array constructor
    runtime_size_bound_class( std::size_t size )
        : runtime_bound_array[ size ]
    {
        // ...
    }
} ;

他にも色々と文法案が提案されているが、どれもこれも一様に気持ち悪い。

まず、データメンバーの宣言文法から見ていこう。これは、実行時束縛配列(runtime bound array)と呼ばれていて、以下のように宣言する

type [] name ;

なぜこうならなければならないのか。当初、runtime bound arrayの文法は、通常のtype name [] ; になる予定だったのだが、それだと、既存のCの構造体のテクニックとかぶってしまうのだ。

// 非常によく使われているテクニック
struct X
{
    std::size_t size ;
    char buf [] ;
} ;

int main()
{
    constexpr std::size_t size = 100 ;
    X * ptr = reinterpret_cast< X * >( std::malloc( sizeof(X) + size ) ) ;
    ptr->size = size ;
}

そのため、文法を変える必要があったのだ。

実行時束縛配列のデータメンバーは、複数持つこともできる。

// 複数個持つ例
struct X
{
    char [] a ;
    char [] b ;

    X( ) : a[ 1 ], b[ 2 ]
    { }
} ;

さて、runtime bound arrayのサイズは、array constructor(配列コンストラクター)と呼ばれるコンストラクターで指定する。

runtime_size_bound_class( std::size_t size )
    : runtime_bound_array[ size ]

array constructorは、メンバー初期化子の文法を拡張して[]でサイズを実行時に指定する。

array constrcutorは、必ず、クラス定義の中で定義しなければならない。

// 間違いの例
struct X
{
    char [] a ;
    X() ;
} ;

// ill-formed
X::X() : a[1] { }

初期化も、通常通りだ

// 初期化の例
X() :
a[1], // デフォルト初期化
b[1](), // 値初期化
c[1]{} // リスト初期化
{ } 

さて、runtime bound arrayをデータメンバーに持つクラスは、runtime size bound class(実行時サイズ束縛クラス)と呼ばれる。runtime size bound classをデータメンバーに持つクラス、runtime size bound classから派生するクラスも、runtime size bound classとなる。

runtime size bound classのオブジェクトは、自動変数として使うことしかできない。つまり、一切の動的に確保する操作は禁止されている。たとえばnewできないし、std::vectorのvalue_typeとなることもできない。

// 禁止例
// ill-formed
new runtime_size_bound_class ; 
// ill-formed
std::vector< runtime_size_bound_class > v ;

runtime size bound classへのsizeofは禁止されている。

// sizeofは許可しないィィィッ!
struct X
{
    char [] a ;
    X() a[1] { } 
} ;

// ill-formed
std::size_t size = sizeof( X ) ;

なぜdynarrayではダメなのかというと、dynarrayで自動ストレージを実行時サイズ確保しようとすると、実装にコンパイラーマジックが必要になるからだ。C++は歴史的にコア言語とライブラリを分割している言語である。C++11では、std::initializer_listという例外が追加されたが、あれは例外中の例外で、基本的には、コア言語とライブラリは直接関わらない。

そのため、ライブラリを実装できる機能は、コア言語で提供されているべきである。そのような機能が、実行時束縛配列というわけだ。実行時束縛配列を使えば、dynarrayが実装できる。

さて、論文では、この提案の他にも、様々な提案をしている。

非inlineコンストラクター

コンストラクター定義をクラス定義の外に書きたい。しかし、配列のサイズの指定方法は、実装の都合上、クラス定義の中になければならない。そこで、メンバー初期化子だけ、inline definition(インライン定義)という名前で、クラス宣言に書くことができる案も、論文に書かれている。

// 提案
struct X
{
    char [] a ;

    // インライン定義
    X() : a[1] { }
} ;

// 本物の定義
X::X() // メンバー初期化子はすでに指定されているので書けない
{
// ...
}

多次元配列

現在の提案では、一次元配列しかサポートしていないが、文法を多次元に拡張することもできる。

// 多次元実行時束縛配列
struct X
{
    char [][] a ;

    X( std::size_t x, std::size_t y )
        : a[x][y]{}
    { }
} ;

sized constructor

サイズコンストラクターといって、コンストラクターをクラス定義の外に書く文法の別の提案。これはDaveed Vandevoordeの提案。

// sized constructorの例
struct X
{
    char [] a ;
    int x ;

    X( std::size_t size, int x ) sizeof( a[size] ) ;
} ;

X::X( std::size_t size, int x ) : x(x)
{
// ...
}

相変わらずだが、Daveed Vandevoordeの提案する文法は、毎回キモい。彼はEDGという不自由なC++コンパイラーフロントエンドの開発者であるので、とりあえず非曖昧でパースしやすい文法を再優先で考案するのだろう。

[PDF早く滅んでくれ] N3876: Convenience Functions to Combine Hash Values

unordered associative container(unordered_map, unordered_multimap, unordered_set, unordered_multiset)は、一般にはハッシュとよばれる仕組みで要素を管理するコンテナーである。具体的には、value_typeから短時間で計算できる短い情報量のハッシュ値を計算して、ハッシュ値同士の比較を行うことで、定数時間の複雑性を可能にしている。

問題は、value_typeからハッシュ値を計算する方法が必要だということだ。標準ライブラリは、基本型やstd::stringなどの標準ライブラリには、ハッシュ値の計算方法を提供している。ただし、ユーザー定義型については、利用者がクラステンプレートstd::hashを特殊化するか、あるいはクラスで実装してテンプレート実引数で渡すなどして、ハッシュ値の計算方法を実装しなければならない。

適切なハッシュ値の計算というのは、とても難しい問題である。平均的なプログラマーがたやすく扱える問題ではない。

たとえば、以下のクラスを考える。

// 顧客クラス
class Customer {
public:
    // ...

    std::string getFirstname() const;
    std::string getLastname() const;
    int getAge() const;
} ;
bool operator== (const Customer&, const Customer&);

このようなクラスのオブジェクトのハッシュ値を計算したい。ところで、都合の良いことに、std::stringやintといった型は、すでに標準ライブラリによって、ハッシュ値を計算する実装が提供されている。これを使って、以下のように実装してはどうか。

// 非常に問題のあるコード例
class CustomerHash
{
public:
    std::size_t operator() (const Customer& c) const
    {
        return  std::hash<std::string>()(c.getFirstname()) +
                std::hash<std::string>()(c.getLastname()) +
                std::hash<std::string>()(c.getAge()) ;
    }
} ;

std::unordered_set<Customer,CustomerHash> coll;

このコードにより生成されるハッシュ値は、極めて質が悪くなる。ハッシュ値は、単に足しあわせてはいけないのだ。

ではどうすればいいのか。筆者はこのレビューを書くにあたって、Donald Knuth先生の大著、The Art of Computer Programming Volume 3を読んだが、やはり、適切なハッシュ値の計算を書くのは難しい。コンテナーという利用目的にあった効率的なハッシュ値を計算しなければならない。ハッシュ値の計算は高速に行われるべきだが、生成されるハッシュ値の質が低くては元も子もない。

そこで、複数のハッシュ値から、まあまあ使える程度のハッシュ値を生成するライブラリを、標準で入れてはどうか。

たとえば、Boostには、そのようなライブラリが存在する。

Combining hash values - 1.35.0
Function template hash_combine - 1.35.0

hash_combineは、たとえば、以下のように実装できる。

// hash_combineの実装例
template <typename T>
void hash_combine (std::size_t& seed, const T& val)
{
seed ^= std::hash<T>()(val) + 0x9e3779b9
+ (seed<<6) + (seed>>2);
}

これは、最高のハッシュ値の計算方法ではないが、単なる足し算よりはいくらかマシな、複数のハッシュ値のハッシュ値の計算方法だ。

議論のしどころはたくさんある。たとえば、seedを直接公開しないようにして、もっといい実装ができる余地を残すなどだ。

[冗長すぎるPDF] N3877: Centralized Defensive-Programming Support for Narrow Contracts (Revision 3)

防衛的プログラミングをサポートするための標準ライブラリ。Bloombergが出したこの論文は、その格調高さに反比例して、中身は薄すぎる。文章量だけは無駄に常用で長いが、本質が薄っぺらい。

要するに、中身はCプリプロセッサーによるassertマクロに毛が生えたようなものだ。assertに引っかかった時の挙動を指定できたり、例外が投げられたりといった機能があるだけのassertだ。

筆者はCプリプロセッサーを使ういかなる機能にも反対しており、この提案にも当然ながら反対する。

[あまりにも冗長なPDF] N3878: Extensions to the Concept Introduction Syntax in Concepts Lite

この提案には、まだ文面案がないので、このレビューの解釈は間違っている可能性がある。そもそも、文法が大幅に変更される可能性がある。

Concept Liteについては、もう十分に有名になったので、いまさら説明するまでもないだろう。Concept Liteは、C++11がまだC++0xと呼ばれていた時代に、一旦はドラフトに入りながら、標準化委員会内でconcept mapを暗黙に生成するべきか、明示的に記述させるべきかで意見が二分されたコンセプトの、テンプレート実引数のチェック部分だけを切り取った、軽量版のコンセプトだ。

たとえば、2種類のイテレーターFor1, For2をマージして、Outというイテレーターで出力可能かどうかを判定するconstexpr関数Mergeableの宣言が、以下のように書かれていたとする。

// Mergeable
template < typename For1, typename For2, typename Out>
constexpr bool Mergeable() ;
// 定義省略

さて、このconstexpr関数をConcept Liteに使いたい場合は、以下のように記述する。

// Concept Liteの例
template < typename For1, typename For2, typename Out >
    requires Mergeable< For1, For2, Out >()
void merge( For1 p1, For1 q1, For2 p2, For2 q2, Out o ) ;

これは冗長で書くのが面倒だ。以下のように書けるようにしてはどうか、という提案。

// N3878提案
Mergeable{ For1, For2, Out }
void merge( For1 p, For1 q, For2 p2, For2 q2, Out o );

このように書けば、最初の長ったらしく書いたものと同じように扱われるようにする提案だ。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3879.pdf

もうすこし順序立てて解説する。まず、従来のunconstrained templateが、以下のようだとしよう。

// unconstrained template
template < typename C >
void function( C ) ;

このテンプレート仮引数Cに対して、UnaryConceptというconstexpr関数を適用して、constrained templateにしたいとする。

// constrained template
template < typename T >
constexpr bool UnaryConcept() ;

requires句を使うと、以下のように書ける。

// requires句を使う例
template < typename C >
    requires UnaryConcept<C>() ;
void function(C) ;

これは面倒だ。そのため、今のConcept Liteの提案は、以下のようなシンタックスシュガーを提供している。

// 便利なシンタックスシュガー
template < UnaryConcept C >
void function(C) ;

class/typenameと書くべきところに、直接constexpr関数名を指定できるのだ。

それを延長して、以下のように書けるようにする。

// N3878提案
template < UnaryConcept { C } >
void function( C ) ;

そして、さらに突き進めて、以下のように書けるようにする(はず、あるいは論文が間違っているのか)

// N3878提案
UnaryConcept { C }
void function( C ) ;

テンプレートの冗長な文法が、だいぶ簡略化された。いや、簡略化し過ぎで、個人的には落ち着かない。しかし、プログラマーというものは、簡単な文法を好むものであるから、むしろこのくらい大胆に簡略化したほうがいいのかもしれない。

この提案されているシンタックスシュガー的な文法が、どのように変換されるのか。まず、以下のようなコード

// N3878提案
SomeConcept{ A, B, C }
void function( A, B, C ) ;

において、SomeConceptはconstexpr関数名である。braceで囲った識別子一つ一つについて、テンプレート仮引数として指定したことになる。

// シンタックスシュガー変換後
template < typename A, typename B, typename C >
    requires SomeConcept< A, B, C >()
void function( A, B, C ) ;

もし、すでに宣言したテンプレート仮引数を使った場合は、ill-formedとなる。たとえば、以下のようなコード

// ill-formedな例
template < typename A, SomeConcept{ A, B } >
void function( A, B ) ;

は、以下のように展開されるので、

// 展開後
template < typename A, typename A, typename B >
    requires SomeConcept{ A, B {
void function( A, B ) ;

ill-formedとなる。

ところで、Concept Liteでは、constrained関数テンプレートを宣言する新しい文法、terse notationを提案している。これは聡明な読者ならば、いまさら説明するまでもないであろうが、念の為に説明しておくと、以下のようなコードが、

// terse notationの例
void sort( Container & c ) ;

以下のように書いたものとみなされる。

// 上記のterse notationと同等のコード
template < Container __Contaiener >
void sort( __Container & c ) ;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3879.pdf

もちろんこれは、以下のような意味だ。

// さらに展開後
template < typename __Container >
    requires Container<__Container>()
void sort( __Container & c ) ;

そう、聡明な読者ならば、もう気がついているだろう。N3878提案の拡張は、このterse notationにも適用できる。

// terse notationのN3878拡張の例
void sort( Container{C} & c ) ;

これは、以下と等しい。

// 同等のコード
template < typename C >
    requires Container<C>()
void sort( C & c ) ;

なぜ、これが役に立つのか。現在のterse notationは、同じコンセプトを満たす別の型を複数、仮引数に取りたい場合、使うことができない。

たとえば、以下のコードは、

void f( SomeConcept a, SomeConcept b ) ;

以下のコードと同じ意味である。

template < typename __SomeConcept >
    requires SomeConcept<__SomeConcept>()
void f( __SomeConcept a, __SomeConcept b ) ;

したがって、もし、aとbが違う型で、どちらの型もSomeConceptを満たして欲しい場合は、terse notationは使えない。面倒でも従来のやり方で書かなければならない。

// 従来のやり方
template < SomeConcept A, SomeConcept B >
void f( A a, B b ) ;

N3878拡張を使えば、上記と同じ意味を、terse notationと組み合わせることにより、以下のように書くことができる。

// N3878提案
void f( SomeConcept{A} a, SomeConcept{B} b ) ;

また、N3878提案で宣言された名前は、宣言されたことになるので、例えばterse notationでも面倒な以下のようなコードが、

// 面倒なTerse Notationコード
void f( RandomAccessIterator first, RandomAccessIterator Last ) ;

以下のように書ける。

// N3878提案
void f( RandomAccessIterator{R} first, R last ) ;

N3878拡張は、新しいテンプレート仮引数を宣言するので、たとえば、以下のようなコードはill-formedとなる。

// ill-formed
void f( RandomAccessIterator{R} first, RandomAccessIterator{R} last ) ;

なぜならば、これは以下と同等の意味になってしまうからだ。

// ill-formed
template < RandomAccessIterator R, RandomAccessIterator R >
void f( R first, R last ) ;

また、現在のConcept Liteの提案では、変数テンプレートもconstrained templateにでき、また、変数宣言の型引数の代わりに使うことができるとしている。

// constrained変数テンプレート
RandomAccessIterator r = std::find( p, q, r ) ;

これは、読者のような本物のC++プログラマーには、いまさら説明するのは失礼に当たるかも知れないが、念の為に解説すると、以下のような意味である。


template < typename __RandomAccessIterator >
    requires RandomAccessIterator<__RandomAccessIterator>()
__RandomAccessIterator r = std::find( p, q, r ) ;

一貫性を保つため、N3878拡張は、constrained変数テンプレートにも適用できる。

// N3878提案
RandomAccessIterator{R} r = std::find( p, q, r ) ;

これは、rの型名に名前をつけることができるという点で、素のterse notationより優れている。decltype(r)などと書きたくはない。

また、提案では、以下のような文法にも触れている。

// どこまで本気かわからないコード
auto{T} t = foo() ;
// Tはtの型

これは・・・いやはや

[明示的PDF警告] N3879: Explicit Flow Control: break label, goto case and explicit switch

これは面白い。

この提案は、break label, continue label(Javaと同等), goto case 定数式, goto default(C#と同等), explicit switch文(C#と同等)

break labelとcontinue labelは、ネストしたfor, while, do-whileから抜けるのに使うことができる。

// break labelの例
beginning_of_the_loop:
for ( auto && elem : v )
    for ( auto && elem : w )
    {
        break beginning_of_the_loop ;
    }

// continue labelの例
for( auto && elem : v )
{
    middle_of_the_loop:
    for ( auto && elem : w )
        for ( auto && elem : x )
        {
            continue middile_of_the_loop ;
        }
}

goto case 定数式は、switch文の中で、caseラベルを指定してgotoするのに使うことができる。

// goto case 定数式
switch( cond )
{
    case 0 :
        break ;
    default :
        goto case 1 ;
}

explicit switchは、caseラベルひとつひとつが、ブロックスコープを持つ。これにより、次のcaseラベルかdefaultラベルに到達した時点で、switch文を抜ける。もうbreakを書き忘れて、下まで突き抜けてしまうという、しょうもないが人間であるがゆえに起こりうるバグに悩まされることはない。また、わざわざブロック文を使わずとも、ブロックスコープになっているので、変数の宣言も楽になる。

// explicit switchの例
explicit switch( cond )
{
    case 1:
        // ...
    case 2 :
        // flag == 1の場合、ここは実行されない
}

連続するcaseラベルは、ひとつのブロックスコープにまとめられる。


explicit switch( cond )
{
    case 1 :
    case 2 :
        // ブロックスコープ開始
        // cond == 1 or 2の場合、ここが実行される
        // ブロックスコープ終了
}

caseラベルがブロックスコープを持つということは、変数ももちろん、スコープに従う。


switch ( cond )
{
    case 1 :
        int x = 0 ;
    case 2 :
        int x = 0 ; // エラー、おなじスコープ
}

explicit switch ( cond )
{
    case 1 :
    // {
        int x = 0 ;
    // }
    case 2 :
    // {
        int x = 0 ; // OK、別のスコープ
    // }
}

ドワンゴ広告

この記事はドワンゴの勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

ValveがDota 2で使われているらしきDirect3D-OpenGL変換のライブラリを抜きだして公開

邪悪なDRM付きのゲーム流通プラットフォームと不自由なソフトウェア実装のゲームを蔓延させているValveが、Dota 2で使われているらしき、ライブラリレベルでDirect3DをOpenGLに変換するラッパーライブラリ、TOGLをGitHubで公開した。

ValveSoftware/ToGL

これは、Direct3D 9.0cのAPIでありながら、中身はOpenGLを使っているという、ラッパーライブラリ、あるいはソフトウェア互換レイヤーとでもいうべきライブラリだ。どうやら、Dota 2というゲームで使われているコードベースから、この部分だけ抜き出して公開したようだ。

DirectX 9.0cのすべての機能を実装しているわけではないという。HLSLバイトコードから、GLSLバイトコードへのトランスレーターを含む。Multiple Render Targetsはサポートしているが、Vertex Texture Fetchはサポートしていない。

また、このままではビルドすらできないし、また、Sourceエンジンの挙動に合わせるためにハードコードした部分もあるという

ところで、このようなライブラリには見覚えがある。そう。ANGLEだ。

angleproject - ANGLE: Almost Native Graphics Layer Engine - Google Project Hosting

ANGLEとは、不自由なMicrosoft Windows環境で、OpenGL ES 2.0環境をDirectX 9ないしはDirect X 11を使って実現するライブラリだ。つまり、TOGLの逆転版ということになる。

ANGLEは、ChromiumとFirefoxで、まともなOpenGL環境のない制限OSであるWindows環境で、WebGLを実装するために使われている。

DirectXはもはやその役目を終えたので、そろそろ終焉に向かって欲しい。

2014-03-09

Amazonのお気に入りリストで送られてきたもの Part 4

さて、またまたアマゾンのAmazon.co.jp: 江添亮: 江添のほしい物リストで物が送られてきた。今回も、また解説を行いたいが、その前に、前回に約束した、TENGAの調査報告を行おうと思う。

前回、TENGAという男性用自慰補助器具が、Amazon.co.jp: 江添亮: 江添のほしい物リスト経由で送られてきた。本来、筆者宛に送られてきたのだから、筆者自らが調査に当たるべきではあるのだが、筆者はこの分野の専門家ではないので、正しく評価できない可能性がある。幸い、今筆者が住んでいるシェアハウスの住人に、この分野における専門家がいるので、彼にプロフェッショナルな評価を下してもらうことにした。この調査員は、専門家とはいいながら、このような補助器具の使用経験はないとのことなので、新鮮な評価を下せることだろう。

さて、自薦によりTENGAの調査員になった専門家に、後日話を聞いてみたところ、曰く、

「江添さん、これサイコーでした。思わず声が出るほど気持ちよかったです」

とのことだった。なるほど、有名ブランドたる品質は備えているようだ。では、本物との比較調査はどうであろうか。残念ながら今回の調査員が実施した調査は、TENGAと本物の盲検法ではなく、また同時に検証したものでもないので、厳密な比較調査とは成り得ないが、

「本物? ああ、うーん、どうだろ。だいぶ前のことなのであんまりよく覚えてないんですよ。あ、でもでも、本物のほうが情緒はありましたね」

との回答が得られた。なるほど、TENGAは「情緒」という点で本物に劣るそうだ。残念ながら、調査員が報告に用いた「情緒」なる用語の定義が与えられていないので、筆者には理解ができないし、また改良案も思いつかない。総じてこの分野は、明文化されていない用語が反乱しすぎていて、筆者の理解の及ぶところではない。

以上をもって、妖怪ハウスによるTENGAの調査結果とする。だいたい、このようなものを筆者の元に送られても、このように至極つまらない文章に成り下がってしまう。読者諸君は、もっと面白いものを送るべきであると考える次第である。

さて、それでは、また送られてきた商品の紹介を行うことにする。

まず送られてきたのは、鍋である。残念ながら、商品名を失念してしまったが、1.5L程度の使いやすい鍋が手に入った。妖怪ハウスの住人は、これまで100円ショップの鍋のような粗悪な鍋を使っていたので、この鍋はとても有益に活用させてもらうことにする。妖怪ハウスに遊びに来た折には、筆者が手料理を振る舞おう。

バリラ No.5 スパゲッティー 5kg [並行輸入品]も送られてきた。

これは、5kgも入っているスパゲティの乾麺の袋だ。シェアハウスで多人数に格安(それでも大赤字なのだが)で手料理を出すべく、肉のハナマサや業務スーパーで買い物をしている筆者だが、まだ5kgのスパゲティの袋にはお目にかかったことがなかった。5kgのスパゲティの袋は、相当に迫力があった。幸い、2kgの巨大なトマト缶を買っているので、いつかひき肉などを仕入れて、ミートソースでも作り、スパゲティパーティを開こうと思う。ぜひ食べに来て欲しい。

なんと、前々から欲しかった、日本製 福助足袋 メンズ4枚こはぜ付き白足袋 テトロンブロード 22cm-29cm が届いた。筆者はすでに雪駄は自前で買っているが、近所に足袋を売っている場所がなく、寒い思いをしていたのだ。これはありがたく使わせてもらうことにする。

さて、これで、ふんどし、雪駄、足袋は揃ったわけだ。他にも和服を揃えたいところだ。また、残念ながら送られてきたふんどしが、赤ふんどしなので、ふつうの白いふんどしも欲しいところだ。

それから、やけに平たくて軽い箱が送られてきた。中には、 マグエックス ホワイトボードMX A2サイズ MXWH-A2が入っていた。こういう手頃なホワイトボードは、筆者も一枚、すでに自前で買っているのだが、もう5,6枚ぐらいはあっても困ることはない。ありがたく活用させてもらう。

そして、危うく見逃すところであったが、ホワイトボードの箱に、32GBのUSBメモリーが同梱されていた。USBメモリーは、いくつあっても困ることはない。ありがたく活用させてもらう。

また、本が一冊送られてきた。 天竜川殺人事件 (祥伝社文庫)という本だ。筆者は、この本、この著者である梓林太郎についてはの知識はない。それでも、本の虫である筆者に本が送られてきたので、あとで読むことにする。

さて、最後に、とても重い箱が送られてきた。その重さは半端ではない。とても重い。いったいどんな素晴らしいブツが入っているのであろうか。期待に胸が踊る。きっと、今までに送られてきたブツのなかで、最高のものが入っているに相違ない。ああ、こんなブツを送ってくれる人がいるだなんて、筆者はなんと幸せものなのだろうか。

喜び勇んで箱を開けた筆者の眼前に現れた待望のそのブツは・・・ブツは・・・ あかぎ園芸 川砂 12Lであった。

15kgの川砂だ。

なるほど、有名な天竜川の洗砂は、いま、アマゾンから在庫が切れている。そこで、これを送ってきたのだろう。まてよ、まさか、先ほどの本は、天竜川つながりで送られてきたのであろうか。何を隠そう、筆者は以前、静岡県の西部に住んでいたことがあるので、天竜川というのは、馴染み深い川なのだ。

さて、この川砂をどう処理したものか。処理するだけなら簡単だ。妖怪ハウスの住人には、庭付きの家を持っている者がいるので、その人の家にまいて処分できる。しかし、それ以外の活用方法も考えたいものだ。

川砂というのは、あまり耕作には適していない。せいぜい、サボテンのような植物しか育たないのだ。妖怪ハウスのベランダには、プランターが設置されているが、いずれ野菜でも栽培しようかと計画している。しかし、川砂では耕作可能な野菜が制限されてしまう。

以上が、今回のAmazon.co.jp: 江添亮: 江添のほしい物リストで送られてきた品物の報告だ。

さて、どうやら執拗に、アマゾンで送れないものがあるので、「第三者出品者へ住所を公開する」設定を有効にしてくれと言ってくる者がいる。これは不思議な話で、筆者はすでに、そのチェックボックスにはチェックを入れているはずなのだ。それにも関わらず送れないという。

そこで、筆者は、妖怪ハウスの住所を公開することにした。妖怪ハウスは、住所を公開しても問題のないところだ。なぜならば、すでに住人の多くが、住所を公開してしまっているので、いまさら筆者が隠したところで、どうしようもないからだ。それに、24時間、複数の住人が家にいるので、空き巣に狙われることはない。強盗のリスクだけはどうしようもないが、しかし強盗は防ぎようのない問題であって、住所を公開したからと言って、強盗のリスクは上がらないだろう。

妖怪ハウスの住所:

郵便番号:165-0027
住所:東京都中野区野方5-30-13 ヴィラアテネ401
宛名:江添亮

なにか、アマゾンを経由しないで、筆者にブログのネタを提供するために品物を送りたい人は、上記の住所に送ってもらいたい。

また、C++を学びたいと思う者、ボードゲームで遊びたいと思う者、C++を話したいと思う者、レトロゲームで遊びたいと思う者、C++な者は、妖怪ハウスまで訪れてもよい。タバコを吸わない者であれば歓迎する。

2014-03-04

Boost.勉強会 #14 東京に参加した

3月1日の土曜日に、Boost.勉強会 #14 東京 : ATNDに参加してきた。

Boost.勉強会というのは、Boostを中心に据えて、C++関連の知識を発表しあう、すっかりプログラマーの間では定着した感のある「勉強会」のひとつだ。Boost.勉強会は、趣旨に賛同する各地のメンバーによって開かれているが、ここ東京では、IIJから部屋を借りて開くのが定着しているようだ。IIJの部屋は広いので、120人まで入れる。

せっかくドワンゴに雇われて、今年からフルタイムでC++の啓蒙活動をしているのだから、自己紹介と宣伝のために、なにか適当なドワンゴTシャツでも着ていくことを思いついた。ドワンゴTシャツぐらい、社内に転がっているだろうと探してみたが、あいにくと、今は超会議用のTシャツしかないそうだ。超会議用のTシャツは、運営スタッフ用のシャツで、ドワンゴの社名は入っておらず、また、大きく「運営」と書かれている。これを着ていくのは、明らかに違うだろう。

超会議といえば、私もスタッフの一人として参加する予定になっている。私は超会議に出る必要はないそうなのだが、ドワンゴ社員のほぼ全員がでるとあれば、出てみるべきだろう。たまには非日常も悪くない。私に割り当てられる仕事はまだわからないが、何かが割り当てられるだろう。

今回が三回目となるこの超会議、初回は、個人の特性を無視して適当に役職が割り振られた結果、悲惨なことになったらしい。一日中、チャーハンを作るハメになったドワンゴ社員が、「俺は中華鍋を振るためにドワンゴに入社したんじゃねぇッ!」と悪態をついたり、特にゲームには興味のないドワンゴ社員がゲームブースに配置されて何もわからず混乱したりしたそうだ。二回目からは希望を取るようにしたそうだが、まあ、すべてがうまく行く非日常などないのだろう。

それはさておき

あるいは、スーツを着た人間の大好きな、死んだ木に印刷された、いわゆる名刺と呼ばれている紙切れを配って、本来不要な紙の浪費に貢献すべきだろうか。あいにくと、私はまだ名刺を作る申請をしていなかったので、今から作ったところで、数日後の勉強会には間に合わない。それに、どうせ名刺を作るのならば、役職をC++ Evangelistにでもしたいものだ。この一ヶ月、人と会うたびに、C++エヴァンジェリストと呼ばれ続けているのだから、いっそのこと正式な肩書にしてしまえばいい。残念ながら、Boost.勉強会には間に合わない。

しかたがないので、ドワンゴステッカーを配ることにした。無難なデザインのドワンゴのロゴのステッカーだ。しかし、このようなものを能動的に配るのは、どうも私の自己紹介というよりは、ドワンゴの宣伝のような気がしてならない。宣伝はいいとしても(他人の勉強会でやるのは好ましくなかったが)、宣伝というものは、あまり露骨にやり過ぎると逆効果である。今回はやり過ぎたかもしれない。

さて、Boost.勉強会の階乗では、会場の提供者であるIIJ社員が、何やら可愛らしいステッカーを配っていた。これはいわゆる萌えというジャンルの絵柄らしい。なるほど、プログラマーの大半は萌えと親和性が高く、萌えステッカーの求心力は絶大だ。よくぞ考えた。この萌えステッカーの威力の前では、ドワンゴのステッカーは霞んでしまう。しかし、IIJはいままで、お堅い企業だとばかり思っていたが、このような柔軟な発想ができるとは思いもよらなかった。と思ったが、話を聞いてみると、なんでもIIJ公式のステッカーではなく、単にIIJ社員が趣味で作った私的なステッカーだそうだ。

さて、肝心の勉強会であるが、今回、私の興味を強く引いたのは、Kumazaki Hiroki氏の、いつからFIFOがスケールしないと錯覚していたであった。Lock Freeの深淵をうかがい知ると共に、「ロックフリー」という呪文は、kumagi神を召喚する呪文なのだという認識を持った。今後うっかりと「ロックフリー」とつぶやこうものならば、すぐさまにkumagi神が虚空から出現して、三回ぐらいプログラマーとしての自信を消失するほどメタメタのギタギタに論破されるであろう。コードを書かずしてそうなるのであるから、ロックフリーなコードを書くという闇儀式を行った日には筆舌に及びがたいほど論破されるに違いない。我々凡プログラマーには、精神の安定のために「ろっくまぎふりー」な環境が必要とされている。いや、それでは自称ロックフリーなクソコードを量産するだけだ。ますますkumagi神を荒ぶらせる結果となってしまう。

さて、勉強会の後に、近くの中華料理屋で懇親会を行った。懇親会では、様々な雑談をした。

懇親会に、Oculus Riftを持ってきている人がいた。これは、あの伝説のゲームプログラマー、John Carmackもid Softwareを辞して開発に参加したほどのHMDだ。かねてからその名前は聞いていたものの、実物を触るのは初めてだ。しかも、実際に体験することができた。Oculus Riftを体験した結果・・・

筆者は未来を見た。

Oculus Rift。これはすばらしい。いや、素晴らしいなどというものではない。これは未来だ。これこそが我々の求めていたバーチャルリアリティだ。しかも、実装方法はあんなにも簡単だったとは。なぜ、いままでこんなものが存在しなかったのか。ああ、ああ。

残念ながら、Oculus Riftの魅力を文章で伝えることはできない。平面ディスプレイで閲覧する読者に映像で伝えることもできない。あれは、とにかく体験するしかないのだ。

技術的な話をすると、Oculus RiftはHMDに屈折レンズと、Hillcrest Labsの6軸加速度センサーを取り付けただけのものだ。HMDに出力する映像を歪めて、さらに屈折レンズで視野全体に投影する。そして、6軸加速度センサーで顔面の向きの動きを検知するのだ。HMDに出力するソフトウェアは、顔面の向き入力を受け取り、出力を対応して変化させる。すると、全方位に顔面の向きを動かしても、映像が追従して変わり、あたかも首を振って周りの景色を眺めているかのような錯覚を引き起こすのだ。視界が完全に映像で満たされ、顔面の方向に従って映像も動くため、信じられないほどの現実感がある。

ああ、なんとこんな簡単な仕組みで、全方位映像が実現できるとは、思いもよらなかった。John Carmackがidを辞めるのも無理はない。これを体験したあとでは、もはや一人の天才が必要とされないゲーム開発などやっていられないに違いない。この技術は、まだ始まったばかりであり、Carmackのような天才を必要としている。

当日用意されたデモ用の映像は三種類あった。ひとつは、トロッコがジェットコースターのような線路をひたすらグルグル回る映像。これは、おそらく人によっては3D酔するだろう。私は3D酔を経験したことがないので、実際の体の動きを伴わずして、映像だけで酔う感覚というのは、よくわからないのだが。しかも、酔い止めを服用すると症状が軽減されたりするらしい。ますます謎だ。

もうひとつは、初音ミクの3Dモデリングを描画するデモ。このモデリングされた初音ミクを描画するデモは、なかなかにきわどい服を着ており、視点をどの方向に向けるかで、性癖がまるわかりという罠をもっている。

3つ目のデモは、Google Street Viewを映すというものだった。顔面の方向に連動してStreet Viewの方向も変わるので、なんと中華料理屋にいながらにして、私の自宅周辺を全方位眺めることができてしまった。

ああ、Oculus Rift。これは素晴らしい。これこそ未来だ。

懇親会では、これだけではまだ不十分で、映像に連動して風を当てるだとか、匂いを生成するだとかの別の感覚を刺激する装置も必要だなどと議論されていた。まあせいぜい、トニーたけざきのマンガに出てきた世界にならぬよう気をつけたがよい。

さて、すでに告知した通り、筆者は今、ドワンゴに雇われている。その仕事は、C++の啓蒙だ。そして、筆者は東銀座の歌舞伎座タワーにあるセミナールームを使って、勉強会を開くことができる。ドワンゴからも、積極的に勉強会を開くように言われている。勉強会を開くには、事前の調査が必要である。一体どのように行えば良いのか。それには、すでに成功している例から学ぶことが重要である。

さて、既存の勉強会を観察すると、単なる技術の勉強以外の目的も見えてくるものである。

そもそも、私は勉強会の「勉強」という部分には、懐疑的である。技術というものは、30分や1時間ほど、教壇に立って板書したものを一回だけ見て身につくものではない。自分で十分に時間をかけて学ばなければならないのだ。そもそも、30分や1時間程度の時間で、数十枚から100枚程度のスライドを流して話をしただけで完璧に理解できるプログラミング上の技術があるのだろうか。

既存の勉強会を観察するに、勉強会というのは、むしろ技術紹介集会とでも改名すべきであるように思う。多種多様な人間が発表するので、自分の専門分野ではない、様々な技術に触れられる。こういうアルゴリズムもあるのだ。こういう文法もあるのだ。こういうソフトウェアがあるのだ。などといった知識を発見する場であるようだ。既存の勉強会では、大まかな主題だけ決めて、発表内容にかなり広い幅をもたせている。

また、勉強会には多種多様な人間が集まるので、通常ならば交流のない別分野の専門家同士が話をすることができる。これは極めて有意義なことであるし、楽しいことでもある。そのためには、懇親会の存在が非常に大きい。というより、多くの勉強会の目的は、勉強よりも、多種多様なプログラマーが集まって話すことにあるのではないかとも思われる。とすれば、話す場を提供するべきか。

ドワンゴで勉強会を主催するには、既存の継続して開かれている勉強会を参考にしなければならない。

まず、日時が重要だ。残念ながら、皆が皆、ドワンゴのような裁量労働制で働いているのではないので、この前の歌舞伎座.tech#2のように、平日の、それも木曜日の夜から深夜までの開催は、参加しにくいのではないだろうか。既存の勉強会にならうと、土曜日の午前中から夕方までとなる。

発表内容は、前述の考察の通り、技術の紹介のために、大きな主題を一つ決めておき、内容に幅を持たせるために、社外からも発表者を募る必要がある。

開催場所は、もちろんドワンゴが入っている歌舞伎座タワーのセミナールームだ。この部屋は108人入ることができるので、勉強会に十分な広さを持っている。また、発表の様子をインターネット上で動画配信する設備も揃っている(残念ながら、閲覧には不自由なソフトウェアが必要になるのだが)

そして、話し合いの場として、懇親会を行わなければならない。これは勉強会に欠くべからざる要素のようだ。これはどうするか。歌舞伎座tech#2のときは、セミナールームでピザとビールとソフトドリンクを配布していたが、やはり他社の中という環境では、腹を割って話すのも無理だろう。やはり、これは私的に幹事となり、周辺に数十人は入れる宴会場を確保して行うべきだろうか。

C++WGの論文の簡易レビューを片付けたら、勉強会の企画も行わなければならない。

なお、筆者は5月24日に開かれる、Boost.勉強会 #15 札幌 : ATNDにも参加して発表することになっている。筆者は普通の退屈な宿泊施設に金を払って泊まるのは、余り趣味ではないので、札幌のどこかに無料で泊まれるところがあればいいのだが。残念ながら、札幌にはギークハウスはないようだ。

ドワンゴ広告

この記事はドワンゴ社内でドミニオンを教わる前に書いた。

ドワンゴはBoost.勉強会に参加するような本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-03-03

Amazonのお気に入りリストで送られてきたもの Part 3

またまたアマゾンの江添のほしい物リストで、物が送られてきた。

こんど送られてきたのはセーラー服だ。たしかに、これは私がコスプレ衣装を大量登録したときに、リストに入れておいたものだ。

ただし、このセーラー服は、とても作りが雑である。布地は薄く、とても服の用をなさない。しかも、上着は中学生の体格だとしても短すぎるし、スカートに至っては、腰の部分の一点をマジックテープで止めるだけで、実質、腰にタオルを巻くのと変わらない作りだ。

無理もない。これは千円以下の値段なのだ。そんな値段でまともなセーラー服が作れるわけがない。そもそも、この服の用途はコスプレ用。大方は彼女にでも着せて楽しむものであろう。

ちなみに、妖怪ハウスでは、同居人のある男が、調査目的のためにこのセーラー服を着用した。まあ、小柄で童顔な体格ではあるが、悲しいかな、君は男なのだよ。

その次に届いたのが、メイド服だ。こちらは3980円ほどしていて、メイド服が一式揃っていた、カチューシャ、手袋、タイツまである。何やら細長い布切れに結ぶためのヒモがついた謎の部品があったが、妖怪ハウスの調査員の間で議論した結果、これは付け襟に相違ないと結論された。

このメイド服も、同じく同居人のある男が、調査目的のために装着して披露した。まあ、後ろ姿は可愛いものの、やはり君は男なのだよ。

そして、もうひとつ送られてきたのが・・・TENGAだ。

確かに、アマゾンで購入できるネタ商品をかたっぱしから探して、自分でリストに入れた商品ではあるが、まさか送られてくるとは思わなかった。値段的には安いので、送りやすかったのかもしれない。

知らない人のために解説すると、TENGAというのは、ある有名なオナホールのブランドだ。オナホールというのは、男性用の自慰を補助するための器具のことだ。その詳細な構造や、具体的な使用方法については省略するが、

さて、TENGAは、セーラー服もメイド服も着た同居人の男が、これもぜひ調査したいと申し出てきたので譲渡した。その使用感や、本物との比較などの詳細な報告は、あとで調査員に取材を行い、次にアマゾンの江添のほしい物リストで送られてきた商品と合わせて、発表しようと思う。ただし、残念ながら、ここ妖怪ハウスは厳格な研究調査の場ではないので、TENGAと本物との盲検法による比較を行うなどといった、厳格な品質の比較調査は望めないことを、あらかじめ断っておく。

このように、妖怪ハウスには、様々な商品の調査員が存在するので、なにか妖怪ハウスで調査を要する商品があれば送ってもらいたい。

ところで、アマゾンの「第三者の出品者の商品の発送」は有効にしているのだが、なぜうまく動かないのだろうか。

2014-03-01

Raspberry Piのグラフィックスタックが自由ソフトウェアとして提供開始

A birthday present from Broadcom | Raspberry Pi

[Phoronix] Broadcom Open-Sources VideoCore IV 3D Graphics Stack

Broadcomが、Raspberry Piに搭載されているGPUであるVideoCore IV 3D graphicsのドライバーとドキュメントを自由なソフトウェアの定義に当てはまる修正BSDライセンスで公開した。

これにより、Raspberry Piのグラフィック周りも、自由なソフトウェアだけで扱えるようになった。

これを受けてRaspberry Pi財団は、Raspberry PiにQuake 3を最初に移植した者に、1万ドルの懸賞金を出すと発表した。

ただし、この公開は、だいぶ慌ただしく行われたらしく、色々と不備があるようだ。このコードを見たものの感想を紹介しておく。

[raspi-internals] Re: Hey, look, QPU docs - raspi-internals - FreeLists

On 28/02/14 22:44, David Given wrote:

> ただ、奴らはVC4アセンブリらしいどでかいソースコードの塊も公開してるぞ > http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz

確かに、これには訳わからんかったレジスターに対するヘッダーが入ってる。例えば、ようやくあの訳わからんかった0x7ee06000にあるハードウェアモジュールがなんと呼ばれているかわかった。残念ながら、レジスターの名前は入っているが、詳細は入ってない。他のモジュールにはそういう詳細もあるんだがな。

READMEに書いてあるが、ヘッダーはすべて、「あるところ」から自動的に生成されたらしい。「あるところ」とやらは公開されたソースには含まれてない。ソースはちょっと汚い。たとえば、同じレジスターが三箇所でドキュメント化されていたりするところがあるぞ。どうも、Androidのソースツリーから急いで生成した臭いな。

bcrm_usrlib/dag/vmcsx/vcincludeに入ってるのはなかなかよさそうだ。

悪い点としては、ライセンスがまともにドキュメント化されてないことで、だから私のこの説明も、技術的な詳細にはあまり触れられない。いくつかのファイルには、テンプレの'Copyright Broadcom All Rights Reserved'が最初にかかれている。オープンソースなものもたくさんある。ほとんどは修正BSDだ(copyright Broadcomでもある)。機密指定と書かれてるのもある。なんにもかかれてないファイルもある。俺が言えることは・・・やれやれだぜ。

そうそう、RTOSもあるな。

で、RTOSのソースはあるんだが、RAM初期化のための重要なスタートアップコードが欠けている(-_-;)

さて、もう寝ないと。こっから面白いものがいくつも見つかるよ。

-- 
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│ "There does not now, nor will there ever, exist a programming
│ language in which it is the least bit hard to write bad programs." ---
│ Flon's Axiom

2014-02-28

2014-01-pre-Issaquah mailingの簡易レビュー Part 2

2014-01-pre-Issaquah mailingが公開された。

前回に引き続いて、C++WGの論文集を解説していく。

N3863: Private Extension Methods

プライベート拡張メソッド(Private Extension Methods, PEM)は、privateな非virtualメンバー関数を、クラス定義の外で定義できる機能だ。

以下のようなコードを考える。

// Foo.h
class Foo
{
public :
    int get_secret() ;

private :
    void set_secret( int value ) ;
    int secret ;
} ;

時に、このヘッダーファイルは、ユーザー側から利用される。そのようなヘッダーになぜ、privateなメンバーの情報を書いておく必要があるのか。よいクラスの条件とは、なるべく多くを隠匿することにかかっている。ユーザーにとって必要最小限のインターフェースしか提供しなければ、ユーザーにとって覚えることが少ないので使いやすくなるし、ユーザーがつまらない低級な実装の詳細にかかわらずにすむようになるし、実装の自由度も上がる。

privateなメンバーは、ユーザーとクラスの派生先からは、利用できない。したがって、ユーザー向けに提供するヘッダーに書いておく必要はない。しかし、クラス定義をユーザー向けとライブラリ作者向けに分けることは、ODRの都合上できない。

クラス定義には、ユーザーと派生クラス向けではなく、コンパイラー向けの要素も存在する。たとえば、コンパイラーはクラスのレイアウトを決定するために、すべての非staticデータメンバーやvirtual関数(vtableによる実装方法を取るコンパイラーにとっては、レイアウトの決定に関わる)の宣言を必要とする。この場合はsecretだ。

しかし、privateな非virtualであるstatic/非staticなメンバー関数はどうか。set_secretは、ユーザーからも派生クラスからも使えない。コンパイラーはクラスのレイアウトを決定するためにset_secretの存在を知る必要はない。とすれば、private non-virtual member functionは、クラス定義の外で定義してもいいのではないか。そうすれば、ユーザー側から存在を隠すことができる。

privateなメンバーをクラス定義に書かなければならない問題はいくつもある。

ライブラリ作者が、クラス定義のprivateなメンバーを追加、削除、シグネチャの変更をするたびに、そのクラスを使う翻訳単位はすべて、再コンパイルしなければならない。しかし、private非virtualメンバー関数は、完全にクラス作者の中だけで完結しているので、そのような再コンパイルは、本来必要がないのだ。

実装上の都合になるが、クラス定義に書くということは、シンボル名がその分増えるということである。シンボル名が増えるということは、shared libraryなどのシンボル名を解決して動的にロードするような機能に、余計に時間がかかるようになる。

内部リンケージを持つ名前をprivateメンバー関数で使うことができない。たとえそのprivateメンバー関数が、クラス作者の翻訳単位でしか使われないとしてもだ。

この問題は、private非virtualメンバー関数を、クラス定義の外で、追加的に宣言、定義できればよいのだ。すなわち、プライベート拡張メソッドの提案となる。そのために、privateキーワードを流用して、新たな文法を作る。

// Foo.h
struct Foo
{
    int get_secret() ;
private :
    int secret ;
} ;
// Foo.cpp
#include <Foo.h>

private void set_secret( int value )
{
    secret = value ;
}

また、private非virtualコンストラクターも、同様に外部定義できる。

// privateコンストラクター
private Foo::Foo( int value ) : secret( value ) { }

プライベート拡張メソッド(PEM)は、staticメンバー関数にも使えるし、内部リンケージ指定もできる。ただし・・・現在提案中の文法では、色々とややこしい。

問題は、staticというキーワードは、staticメンバーの宣言にも、内部リンケージの宣言にも使われているということだ。そのため、staticキーワードは、位置に酔って意味が変わる。

  • privateキーワードの後にstaticキーワードを書くと、staticメンバーになる。
  • privateキーワードの前にstaticキーワードを書くと、内部リンケージを持つ。
  • privateキーワードの前後にstaticキーワードを書くと、staticメンバーで内部リンケージを持つ。
// staticキーワードの利用例一覧
struct Foo{ } ;

private void Foo::f() ; // private non-static member function
private static void Foo::f() ; // private static member function
static private void Foo::f() ; // private member function with internal linkage
static private static void Foo::f() ; // private static member function with internal linkage

これはあまりにもわかりにくい。

まだC++11がC++0xと呼ばれていたドラフト段階では、一時期、内部リンケージを指定するためのstaticキーワードの使用は、deprecated扱いであった。後に覆ったが、こうしてみると、やはりstaticキーワードを内部リンケージを指定するために使うのは、間違っている気がする。

C++11では、無名namespaceが追加されたので、これを使うことにより、内部リンケージにできる。

// 無名namespaceを使って内部リンケージにする
namespace
{
    private void Foo::f() ; // private non-static member function with internal linkage
    private static void Foo::f() ; // private static member function with internal linkage
}

論文では、プライベート拡張メソッドを、デフォルトで内部リンケージにしてしまうという案も提示している。外部リンケージが欲しければ、明示的にexternキーワードを書くようにする。結局、多くの利用例はデフォルトが内部リンケージで問題ないだろうから。

// デフォルトで内部リンケージ案
private void Foo::f() ; // private non-static member function with internal linkage
private static void Foo::f() ; // private non-static member function with internal linkage
extern private void Foo::f() ; // private non-static member function with external linkage
extern private static void Foo::f() ; // private static member function with external linkage

あるいは、privateキーワードの利用自体を省いてしまうという案もあるが、これは賛成できない。

ところで、誰でもクラス定義の外でprivateメンバー関数を宣言できてしまうというと、アクセス指定の回避ができるかどうかが問題になるところだ。これは、通常は問題がない。なぜならば、誰でもprivateメンバー関数を宣言できるとはいえ、呼び出すことはできないからだ。

// クラスGodivaを定義しているヘッダー
#include <Godiva.h>

private auto Godiva::peeping_tom()
{
    return naughty_bits ;
}

int main()
{
    Godiva godiva ;
    auto dirty_view = godiva.peeping_tom() ; // ill-formed、盲目となる
}

しかし、それでも規格の抜け穴を縫うような形で、プライベート拡張メソッドを使って、合法かつアクセス指定を破れるコードが存在する。


class A {
  int n;
public:
  A() : n(42) {}
};

template<typename T> struct X {
  static decltype(T()()) t;
};
template<typename T> decltype(T()()) X<T>::t = T()();

int A::*p;
private int A::expose_private_member() { // note, not called anywhere
  struct DoIt {
    int operator()() {
      p = &A::n;
      return 0;
    }
  };
  return X<DoIt>::t; // odr-use of X<DoIt>::t triggers instantiation
}

int main() {
  A a;
  return a.*p; // read private member
}

しかし、このようなコードは、うっかりと引っかかる種類のコードではない。プログラマーが意図的に行わない限り、遭遇することのないコードだ。Herb Sutterがかつて言ったように[GotW076] 、

これは実際、問題ではない。この問題は、マーフィーの法則から保護する VS マキャベリから保護するかでしかない。つまり、うっかりミスから守るか(これは言語がとてもうまくやっている)VS 意図的な悪用から守る、かだ。結局、もしプログラマーが体制を破壊したいのであれば、例1から3で示したように、必ず方法をみつけるものだ。

訳注:
マーフィーの法則=よくあることを意味するレトリック
マキャベリ=目的のために手段を選ばないことを意味するレトリック

GotW #76: Uses and Abuses of Access Rights

その他、色々と反論に対する反論が書かれている。例えば、モジュール機能によりこの問題は解決するという反論には、モジュールはいつ入るかわからない。いま使える機能が欲しい。そのためには最小限度の変更で実装できる機能でなければならないと反論している。

また、クラス定義を再び開ける案も書かれている。これは、クラスのレイアウトを変化させるようなメンバーは宣言できないが、private non-virtualメンバー関数以外にも、nested typeなどを追加できる。

// クラス定義を再び開く案
class Foo { } ;

// 再び開く
private Foo
{
    void f() ; // private member 
    int x ; // static data member
} ;

これは興味深い提案だ。

N3864: A constexpr bitwise operations library for C++

C++にビット列操作ライブラリを追加する提案。

<cmath>と<memory>に、constexprでnoexceptなビット列操作のための関数テンプレートを大量に追加する。

ビット列操作は、古くからプログラマーの実用的テクニックでもあり、遊びでもあった。ビット列操作には、実にさまざまな技法が発見されている。

よく使われるビット列操作は、ハードウェアでサポートされていることもある。しかし、CやC++では、PDP-11ですら提供しているビット列操作のインストラクションを、直接使うべき文法が存在しなかった。ビット列操作というのは、プラットフォームごとに最適な実装方法が異なる。多くのプラットフォームに対応したライブラリを実装するには、#ifdefの塊になってしまう。

信じられないことに、この2014年になっても、CとC++には、ビット列操作の文法が極めて貧弱で、標準ライブラリも存在しない。それゆえ、プログラマーは各自に独自ライブラリを作成したり、適当にネット上で検索してコピペしたりしている。

これは極めて残念なことだ。このような汎用的な処理は、共通のライブラリを作るべきなのだ。そして、標準ライブラリということになれば、たとえばコンパイラーは最適化で、プラットフォームによっては単一のインストラクションを吐いたりできる。また、複数のインストラクションを組み合わせなければならない場合でも、文脈に合わせて最適化をかけられるため、単なるインラインアセンブリ以上のことができる。

さて、ビット列操作ライブラリを付け加えるにあたって、問題がある。ビット列操作はとても多いが、いったいどの操作を標準ライブラリに含めるべきか。また、命名はどうするべきか。

どのようなビット列操作を付け加えるべきかという問題に対しては、もちろん、ハードウェアでネイティブにサポートされているビット列操作も考慮するが、それ以外にも、たとえ現実のハードウェアでネイティブにサポートするものがなくても、よく使われる有名で基礎的なビット列操作も含める方針だ。

命名方法はバイク小屋議論となるので難しい。たとえばビット列の末尾に連続するゼロを数え上げる(Count Trailing Zeros)ビット列操作を考えよう。

まず、英語の頭文字をとった、std::ctz()が考えられる。これはアセンブラーで使われているニーモニックによく似たスタイルの命名法で、昔まだ識別子の長さがそうとう短く制限されていた時代の名残である。これは曖昧でわかりにくいが、タイプ数を節約できる。

あるいは、std::count_trailing_zeroes()だろうか。これは、たしかにわかりやすいし、曖昧性もないが、長ったらしいし、複雑な式の中で使うのは難しい。

提案された論文での命名規則は、ニーモニックよりの改良案となっている。

すべての関数名は動詞から始まる。動詞は、少なくとも3文字を使って略字とする。そのため、std::ctz(Count Trailing Zeroes)ではなく、cnttz(CouNT Trailing Zeros)となる。

さらに、0と1に対しては、0と1を用いる。ZやOや、その他の文字は用いない。これにより、cntt0(CouNT Trailing 0)となる。

名詞は、一貫性を持って再利用できる場合、一語一文字で略される。たとえば、以下のような名詞を再利用する。

  • t0: trailing 0s
  • t1: trailing 1s
  • l0: trailing 0s
  • l1: trailing 1s
  • ls1b: least significant 1 bit
  • ms1b: most significant 0 bit
  • ls0b: least significant 1 bit
  • ms0b: most significant 0 bit

ここ何年も、純粋に規格漬けになっていた筆者としては、std::count_trailing_zeros()の方が、曖昧性なくわかりやすくていいのではないかと思う。識別子の長さは、clang-completeのような名前補完ツールを使えばいいのだ。

ちなみに、ドワンゴ社内では、std::ctz()やstd::cntt0()で何の問題もないとする人間ばかりだった。思うに、これは慣れの問題だと思う。ドワンゴ社内のプログラマーというのは、ビット列操作を自前で書くし、アセンブリ言語のニーモニックを日常扱う人間ばかりなので、このような略字に慣れているのだろう。あるいは、現場のプログラマーは、補完ツールが発達した今でも、タイプ数の大小、ソースコード内の一行に収まる情報量という物理的な要素を強く意識するものなのかも知れない。

筆者は、アセンブリ言語は10年ほどやっていないし、それにやっていた時も、マクロを多用して暗号的にわかりづらいニーモニックをまともな名前にしていたし、まだ少しは読めるDSLを実装していた。そういえば昔、自作したISAバス接続の基板をつなげて、MS-DOSから入出力ポートを直接叩いて自作の基板と通信する課題で、言語は自由だったので、他の皆がアセンブリで苦労して書いている中、筆者は16bit DOS用のバイナリが吐けるDigital Mars C++コンパイラーを使って、悠々とC++で高級な入出力ポート操作用のライブラリを使って、入出力ポートを叩いていたものだ。今思えば、筆者は変わり者だったのかも知れない。

それにしてもこの論文は、ドワンゴ社内でも特に食いつきがすごかった。筆者の周辺の人間は皆、論文やGitHubに上がっているリファレンス実装を積極的に読み、これは良いの、あれは悪いの、それは疑問と盛り上がっていた。やはり、ビット列操作に多少なりとも興味を示さないプログラマーは、本物のプログラマーとはいえないだろうし、それに、ドワンゴ社内の仕事でもビット列操作は必要であり、多用されているからだ。

このような現場の知見を得られるというのは、もう何年も規格ばかりやっていた筆者にとっては、なかなか悪くない環境だ。C++標準化委員会としても、感想すらやってこないものに対応できるわけがない。何が良い、何が悪い、何がわからないということは、言わなければ伝わらない。C++標準化委員会にエスパー能力を求めてもらっては困る。本来、日本のC++を扱う企業は、もっとC++標準化委員会に知見を上げるべきなのだ。C++を使っているのに、不満点を言わなければ、いつまでたっても不満は解消されない。社内に実績あるライブラリがあれば、標準ライブラリとして提案しなければ、いつまでたってもC++の標準ライブラリは貧弱なままなのだ。日本の企業はもっと積極的にC++規格に関わる必要があると思った次第。

[PDFに改良案はない] N3865: More Improvements to std::future<T>

futureを更に改良する提案。

現在のfutureは、値と例外を同時に扱っている。


#include <thread>
#include <future>
int main()
{
    auto f = std::async( []() -> int
    {
        throw 0 ;
        return 0 ;
    } ) ;

    // 例外が投げられる
    int result = f.get() ;
} 

future/promise/asyncは、新しくC++11に追加された標準ライブラリexception_ptrを使って例外を束縛し、スレッドを超えて例外を伝えることができる。問題は、もしasyncに渡した関数オブジェクトが例外を外に投げた場合、futureのget()は、例外を投げる。

futureのgetは、値と例外を一緒くたにあつかっている。これは様々な点で不便だ。たとえば、例外を投げてほしくない場合、直ちにtry { } catch( ... ) { }などで囲まなければならないし、その場合でも、やはり例外を投げているわけで、無駄なコストが発生する。

また、futureが持っている例外をexception_ptrの形で欲しい場合でも、やはり一度投げさせてtry catchで受け止めなければならない。なんという無駄だろうか。

そもそも、future自体は、値を持っているのか例外を持っているのか、知っているわけだ。futureが今、readyで、しかも値を持っているのかどうか調べることのできるメンバー関数を追加してはどうか。

そして、値を取得するメンバー関数、get_valueと、exception_ptrを取得するメンバー関数、get_exceptionも追加する。


std::future<int> f = ...

if( f.has_value() )
{
    // 値を持っている
    int result = f.get_value
}
else
{
    // 例外を持っている。
    std::exception_ptr ptr = f.get_exception_ptr() ;
}

ところで、このようにhas_valueでしらべてからget_valueを使うのは面倒だ。もしfutureが値を持っておらず例外を持っている場合に、実引数に指定した値を返すちょっとした関数が欲しい。それがvalue_orだ。

// value_orの例
x = f.value_or(v) ;

このコードは、以下のように書くのと等しい。

// 同等のコード
x = (f.has_value()) ? f.get_value() : v ;

nextは、thenと似ているが、futureに値がセットされている時のみ関数オブジェクトが呼ばれる。

// nextの例
f.next( []( auto f )
{
    auto value = f.get() ; // 必ず値がセットされている
}) ;

recoverは、thenと似ているが、futureに例外がセットされている時のみ関数オブジェクトが呼ばれる。recoverの引数は、std::exception_ptrとなる

// recoverの例
f.recover([]( std::exception_ptr ptr )
{
// ptrは例外を束縛している
}) ;

futureに例外がセットされている時、フォールバックとしての値を使いたい時がよくある。fallback_toは、そのような利用例のためのメンバー関数だ。

// fallback_toの例
x = f.fallback_to(v) ;

これを真面目に書くと、以下のようになる。

// 真面目に書いた例
x = f.then( [&]( auto f )
{
    return f.value_or(v) ;
}) ;

make_exceptional_futureは、例外がセット済みのfutureを作れる。make_ready_futureの例外版といったところだ。

// make_exceptional_futureの例
auto f = std::make_exceptional_future<int>( 123 ) ;

たしかに、値と例外が一緒くたになっているのは不便だ。これはなかなかいい提案だ。

N3866: Invocation type traits (Rev. 2)

C++に新たなtype traits、invocation_typeを追加する提案。

invocation_typeはメタ関数で、メタ関数引数は関数型、関数型の戻り値の型にクラスを、仮引数リストに、実引数の型リストを与えると、実際に呼び出す関数型(あるいはメンバー関数型)を返す。

// invocation_typeの例
struct C
{
    int operator() ( double, int ) ;
    int operator() ( double, double ) ;
} ;

// int ( double, int )
using type1 = std::invocation_type< C ( int, int ) >::type ;
// int ( double, double )
using type1 = std::invocation_type< C ( double, double ) >::type ;

invocation_type< Fn( ArgTypes ... ) >は、Fnを実引数ArgTypesで関数呼び出ししたときに、どのような型の関数が選ばれるかを、::typeで返すメタ関数である。result_ofは呼び出した結果の型を返すが、invocation_typeは、呼び出される関数の型を返す。これにより、呼び出される最適関数のformal parameterを得ることができる。

なるほど、たしかに面白いが、いったいどのように利用するのか。これはMore Perfect Forwardingを実装するのに使う。

たとえば、以下のようなコードは、より完全な転送ができないので、コンパイルエラーになる。

// More Perfect Forwardingが必要な例
void f( int & i ) ;

int i ;

int main()
{
    f( i ) ; // well-formed
    std::thread t( f, i ) ; // ill-formed
}

見ての通り、より完全な転送が失敗している。このコードをうまく通るようにするには、threadの実装で、最適関数に選ばられる関数の実際の仮引数の型を知る必要がある。そのため、invocation_typeが必要になる。

実は、invocation_typeは、より直接的な、raw_invocation_typeのラッパーである。invocation_typeは、もし第一引数がメンバーへのポインターであり、第二引数がrvalueリファレンスである場合、decayを適用してリファレンスを外す。これは、すぐに寿命が尽きる一次オブジェクトを束縛してしまうのを防ぐためである。raw_invocation_typeは、そのような処理を行わない、生の関数型を返す。

さらに、提案では、function_call_operatorを提供している。これは、::valueで、オーバーロード解決で選ばれたメンバーへのポインターを返すメタ関数である。

// function_call_operatorの例
struct C
{
    void operator ()() ;
    void operator ()( int ) ;
} ;

int main()
{
    auto fco = std::function_call_operator< C ( int ) >::value ;
    C c ;
    c.*fco(0) ; // call C::operator()(int)
}

これはぜひとも入って欲しい。

N3867: Specialization and namespaces (Rev. 2)

別の名前空間からテンプレートの明示的特殊化と部分的特殊化ができる提案。

ユーザーがテンプレートを明示的に特殊化することを前提とした設計のライブラリがある。たとえば、std::hashだ。このテンプレートは、ユーザー側がユーザー定義型に対するハッシュの計算方法を指定するために、ユーザーに明示的に特殊化させることを想定している。

問題は、その特殊化には、同じ名前空間であることを必要とするので、面倒なのだ。クラスを定義したら、名前空間を閉じて、目的の名前空間を開き、また閉じて、さて、また元の名前空間を開いて、続きを記述しなければならない。


namespace A {
  namespace B {
    /* ... */
    class C { 
      /* ... */ 
    };
    // hashの明示的特殊化を宣言したい  
  } // Bを閉じる
} // Aを閉じる 

// stdを開く
namespace std {
  template<>
  struct hash<A::B::C> {
    size_t operator()(A::B::C const &c) { /* ... */ }
  };
} // stdを閉じる

namespace A { /* さっきまで使っていた名前空間を開き直す */
  namespace B { 
      /* ... */
  }
}

こんなコードは書きたくない。以下のように書きたいものだ。


namespace A {
  namespace B {
    /* ... */
    class C { 
      /* ... */ 
    };
      
    template<>
    struct ::std::hash<C> {
      std::size_t operator()(C const &c) { /* ... */ }
    };
    /* ... */
  }
}

このように書けるようにする提案。

N3869: Extending shared_ptr to Support Arrays, Revision 1

shared_ptrで、配列を直接サポートする提案。これまでは、カスタムデリーターを渡してやれば、配列を扱うこともできた。しかし、もっと直接的に、

// こんなこといいな、できたらいいな
std::shared_ptr< int [] > ptr{ new int [10] } ;

こう書きたいはずだ。すなわち、shared_ptr<T[]>が、直接サポートされていて欲しい。これをサポートする提案。

論文では、shared_ptr<T[N]>のサポートも提案している。unique_ptrでこれが取り除かれたのは誤りであるとし、むしろunique_ptrにもT[N]を追加すべきだと主張している。

また、論文では、reinterpret_pointer_castという関数テンプレートを提案している。これは、shared_ptr<U>からshared_ptr<T>に変換するものだ。論文はこれをあまり強く主張しておらず、もし削らなければならないのであれば、必要な犠牲として受け入れるとしている。

実装は簡単で、既存のshared_ptrのコードを劇的に変更する必要はない。

Boost 1.53のshared_ptrは、この提案通りに配列をサポートしていて、テストやドキュメントも揃っている。

N3870: Extending make_shared to Support Arrays, Revision 1

N3869と関係していて、make_shardを配列に対応させる提案。

前回の論文、N3641との違いは、寄せられた意見を元に、オーバーロードを極端に削った。今の提案がサポートしているのは、2パターンの利用例だ。

// shared_ptrで配列を確保する例

// 値初期化されたN個のT型の配列、new U[N]()と等しい
// std::shared_ptr< int [ ] >
auto p1 = std::make_shared<int>( 10 ) ;
// std::shared_ptr< int [10] >
auto p2 = std::make_shared< int [10] >( ) ;

// 指定した値で初期化するもの、std::vector<U>コンストラクターと等しい
// std::shared_ptr<int [] >
auto p3 = std::make_shared<int>( 10, 0 ) ;
// std::make_shared< int [10] >
auto p4 = std::make_shared< int [10] >( 0 ) ;

以前の提案では、二次元配列の確保などの、やたらと複雑なオーバーロードが存在した。

N3871: Proposal to Add Decimal Floating Point Support to C++ (revision 2)

十進浮動小数点数をサポートする提案。decimal32, decimal64, decimal128という名前のクラスが提案されている。

C++の標準規格では、浮動小数点数がどのように表現されているかを定めていない。したがって、規格上は十進浮動小数点数で実装することも可能であるが、既存のC++実装はすべて、速度を重視して、浮動小数点数の内部表現は二進数にしている。

十進浮動小数点数の利点は、10進数を正確に表現できることである。たとえば、十進浮動小数点数を使えば、二進浮動小数点数では正確に表現できなかった、10進数の0.1が、正確に表現できるようになる。

論文では、C++03向けに書かれた十進浮動小数点数のTechnical Reportを参照して、C++14用に修正している。この提案が規格入りすれば、C++17では、十進浮動小数点数のサポートは、規格上、必須になる。

C++03向けのTRをC++17向けに書きなおすにあたってなされた変更も興味深い。

まず、10新浮動小数点数型を、Standard layout typeかつPODにするために、明示的にdefault化された宣言を使う。

また、long longへの変換関数は、暗黙的でないほうがいいだろうということで、explicitになった。

// explicitな変換関数になった
decimal32 d = 123.0 ; // OK, doubleからdecimal32は暗黙に変換できる
long long i1 = d ; // ill-formed、decimal32からlong longは暗黙に変換できない
long long i2 = static_cast<long long>(d) ; // OK

また、十進浮動小数点数はクラスではあるが、実装により組込型扱いすることを認めるために、finalとなる。つまり、派生することができない。

ちなみに、ドワンゴの業務で十進浮動小数点数の需要があるかどうかを聞いてみたところ、「あんまりなさそうな」という答えが返ってきた。

ドワンゴ広告

この記事もドワンゴの勤務時間中に書いた。ドワンゴはC++の啓蒙活動を進めている。

ドワンゴは仕事のできるC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-02-27

AtomとかいうGitHub発の不自由なテキストエディターについて

GitHubが存在を公開した(流出したと言うべきかもしれないが)、Atomというテキストエディターの話題で持ちきりである。

このテキストエディターは、邪悪な不自由ソフトウェアであるので、自由の価値を重んずる読者は使ってはならないことはもちろんである。自由、不自由をさておいても(もちろん、さておくことはできない相談だが)、もちろん、敬虔なVim教徒である読者は即座に了解しているだろう。AtomがEmacsよりはいくらかは--自由の価値を重んじない浅はかな利用者にとっては--使いやすくなる可能性はないでもないが、Vimの牙城を崩すことは不可能である。Vimを倒すものはVimであり、NeoVimかもしれないが、Atomであることはありえない。その点で、我々信徒は安心できる。

さて、このAtomというテキストエディターは、自由ソフトウェアではない。その理由は、以下で言及されている。

Why is Atom closed source? - Atom

Atomはクローズドソースとはならないが、オープンソースともならない。Atomはその中間的な位置に立つ。このことによって、我々はAtomに対して金を超集することを容易にするが、ソースコードは何らかの制限的なライセンスで提供されるために、ユーザーは実装方法を調べることができる。我々はどのようにしてこれを実現するかまだ完全に決定していない。公式に発表する際に、詳細を開示できるだろう。

Hacker Newsに興味深いコメントがあった。

Why is Atom closed source? | Hacker News

georgemcbay

GitHubが自分のとこのソフトウェアをどうしようと連中の勝手だが、思考実験としては興味深い。

ここに、少なくとも二つの会社が、大規模なChromiumベースのエディターを開発している。一社はAdobeで、もう一社はGitHubだ。

一社は、エディター技術のコア部分を、完全にオープンソースモデル(もちろん、GitHubでホストされている)で開発していて、すでによく知られていて広く使われているライセンスを採用している。もう一社はやっていない(少なくとも、現時点ではその計画はない)

2年前、オープンソースな方のエディターをやってるのがAdobeだと、誰が正解できただろうか。

まあ、どうせAtomは失敗するだろう。

ところで、IntelのCPUブランドに同名のものがあって、ググラビリティに影響しそうだが、そのへんはどうなのだろう。

ドワンゴ広告

この記事はC++とは関係がないがドワンゴでの勤務中に書いた。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

2014-02-26

アマゾンのお気に入りリストで送られてきたもの

またまたアマゾンでものが送られてきた。

ゲノム 2 (カラフルコミックス)は、古賀亮一の描いたマンガである。このマンガは、昆虫について楽しく学べる教育マンガであるので、是非読んでもらいたい。

スーパーマリオ64は、ゲーム用制限コンピューターであるニンテンドー64上で動作する不自由ソフトウェアだ。残念ながら、いま妖怪ハウスには、ニンテンドー64は置いていない。いずれ買ってこようかとも思うのだが、私はニンテンドー64には、それほど思い入れがないので、今すぐ買ってこようとも思わない。まあ、いずれ、N64を手に入れた時に、感想を書くとしよう。

ただ、ニンテンドー64といえば、風来のシレン2 鬼来襲シレン城は、名作だ。

古賀亮一のゲノムの他の巻や、他のマンガ、また、風来のシレン2なども入っている江添のほしい物リストは以下にある。何か送れば、このブログのネタになる。

Amazon.co.jp: 江添亮: 江添のほしい物リスト

2014-02-25

渋ハウスと立ちション禁止とタバコ禁止

22日に渋ハウスでパーティがあったので、行ってきた。

渋ハウスというのは、一軒家に30人以上住んでいるシェアハウスだ。いや「住んでいる」というのは間違いかも知れない。渋ハウスに正式に金を出している人間が30人以上いるだけで、毎日寝泊まりしている人は30人もいないはずだ。それから、「シェアハウス」というのも違う気がする。人が集まれる場と言ったほうが正確だろうか。

とても大勢の多種多様な人間が集まってパーティをしていた。

残念ながら、私と話題が合う人は少なかった。

渋ハウスは、以外に綺麗なところだった。こんなに大人数を読んでパーティをするところなのに、なぜ綺麗なのだろうか。その謎は、トイレに入った時に解決した。

トイレには張り紙があり、曰く、「立ちション禁止」

なんと、立ちション禁止とな。立ちション禁止とはうーむ。立ちション禁止・・・

立ちション禁止。それは男としての尊厳の否定にほかならない。およそ、男を男たらしめ、女と境するものは、立ちションの可否である。この近代的な男女平等の世の中でも、男が先天的に女より優れているのは、両性における泌尿器の先端器官の違いである。むろん、女でも、姿勢と小便器の形状を工夫すれば、あるいは立ちションも可能かも知れないが、男に比べて極めて非効率的であると言わざるを得ない。立ちションは効率的である。男用の便所が混むことはまれであるのも、立ちションのおかげである。立ちション、これこそ男と女を分かつもの。

しかし、渋ハウスで立ちションが禁止とあっては仕方がないので、ズボンをおろして便座に座って用を足した。

しかし、立ちションの禁止だけでは、トイレ以外の場所は汚れるはずだ。一体、渋ハウスはどうやってこの綺麗さを維持しているのだろうか。なんと、それはタバコが禁止であるがためだ。そうだ。渋ハウスではタバコが禁止なのだ。実に素晴らしいことだ。この点は妖怪ハウスも見習って欲しいところだが、残念ながら妖怪ハウスはまだその域に達していない。まあ、吉田寮よりはマシであると言えるか。

しかし、タバコ禁止と立ちション禁止を天秤にかけると・・・いや、タバコは絶対悪である。もし、タバコと立ちションを天秤にかけると、片方は地面にめり込み、もう片方は脱出速度に達するであろう(はたして地球の重力を使って地球の重力を振りきれるのかという疑問はさておき、たとえ非科学的にせよ、それぐらいの差だということだ)

渋ハウスはとてもいいところであった。住む場所ではないが、遊びに行く場所としては素晴らしい。それに場所も、名にし負う渋谷の駅から近く便利だ。夜中に都内中心部にいて、終電で野方に間に合わない場合に、ああいう場所にも住んでいると便利だ。渋ハウスには金を出してみたい。

さて、シェアハウスかどうかは疑問だが、またひとつシェアハウスめぐりをした。次はどこへ行こうか。しかし、開放的なシェアハウスはあといくつ残っているのか。

ギークハウス東上野

すこし間があいてしまったが、この間、ギークハウス東上野に行って、カレーを食べてきた。

ギークハウス東上野で、カタンをやれそうな雰囲気であったが、残念ながらカタンがギークハウス東上野には存在しない。なんでも、近くにあるコワーキングスペース的なところにあるらしい。しかし、自宅にカタンを持っていない程度であれば、ギークハウス東上野勢は所詮、それほどカタンが強くないのかも知れない。ただし、筆者もポータブルカタンを持っていなかったので、この機会に買っておいた。

定期的にカレーなどを作っているそうなので、また来たいところだ。

さて、筆者のシェアハウスめぐりはまだまだ続く。次はどこへ行こうか。

2014-02-24

Bram MoolenaarがNeovimに反応

Neovim - Google Groups

Vim作者であるBram MoolenaarがNeovimに対してコメントを返している。

大変な仕事になるし、すべてのシステムをサポートすることもできないし、新しいバグが生まれるし、利用者にとって何の価値があるというのだ?

完全なリファクタリングは解決ではない。今あるものを改良するほうがいいのだ。利用者にとってVimが快適になるように、小さなリファクタリングをするのならまだわかるが。

Neovimのニュースを見た時に、まっさきに思い浮かんだし、Hacker Newsでも言及されていたことに、Joel Spolskyのブログ記事がある。

Things You Should Never Do, Part I - Joel on Software

Joelは、MozillaがNetscapeがスクラッチから書き直したことを批判し、たとえどんなにコードが汚かろうと、今動いているものを少しつづリファクタリングして使うべきだと書いていた。それとかぶる。

筆者は、Neovimの動きは好ましいように思う。Vimを吸っクラッチから再実装するのではなく、今あるコードベースを、劇的ではあるがリファクタリングするのだから。

2014-02-23

興味深かった記事

Ubuntu desktop moving application menus back into application windows | Ars Technica

UbuntuのUnityは、長らくウインドウのメニューをウインドウ自体ではなく、画面上部のバーに表示するUIを採用してきた。これには賛否両論あったが、賛同する者達でさえ、問題点は皆無とは言えない状況であった。

グローバルなバーが表示するのは、現在フォーカスのあたっているウインドウのメニューであるので、ダイアログを開くソフトウェアなどが使いづらい。

Ubuntu 14.04では、どうやらメニューをウインドウごとの表示に戻すようだ。

The world’s fastest VP9 decoder: ffvp9 | Ronald S. Bultje

ffmpegによる、最初から自由なVP9デコーダーの実装ffvp9を開発し、Googleの実装であるlibvpxと比較した結果、ffvp9の方がパフォーマンスで上だったという主張の記事。

H.264を使うよりは、Googleが邪悪であるそぶりをみせないうちは、VP9を使ったほうがまだマシだという気がする。ただし、真にクソのような物理法則と関わらないにも関わらず認められている特許から解放されるためには、いまと全く違った動画の圧縮技術が必要とされる。

neovim/neovim

Neovimというレポジトリだ。

確かに、Vimは世界一素晴らしいエディターであり、Vim本体とプラグインには多数の開発者がいる。Vimより優れたテキストエディターが存在しない現状で、Vimの牙城は少しも揺るがない。

しかし、Vimのコードは汚い。20年以上もの歴史を持ち、いまだにC89を使っていて、30万行もあり、その全容を理解している者は少ないし、理解しようという勇者も少ない。

さらに、事実上唯一のメンテナーであるBram Moolenaarは、パッチの受付にとても保守的である。というのも、一度パッチを受け入れたならば、そのコードは、彼が一生保守しなければならないのだから。

Neovimは、現在のVimのソースコードを劇的にリファクタリングすることを目的としたプロジェクトで、以下の目標を設定している。

  • 保守を簡単にし、バグ修正や機能をマージする速度を改善する
  • 複数の開発者で作業を分担できるようにする
  • コアのソース部分に手を加えずに、新しい近代的なユーザーインターフェースを実装できるようにする
  • コプロセスベースの新たなプラグインアーキテクチャにより、拡張性を高める。エディターから特別にサポートしなくても、プラグインを好きな言語で書けるようにする

レガシーコードや、対象コンパイラーがC89という制限を完全に撤去する。また、いままでVimが独自にやっていたプラットフォーム別の実装も、既存のライブラリを利用する。

プラグインは、それぞれ別のプロセスで動作させ、stdin/stdoutを経由して、msgpack-rpcかjson-rpcでプロセス間のメッセージやりとりで動作するという。これにより、Vimのバイナリで言語を一つづつサポートする必要はなくなる。

このマルチプロセス設計は、GUIアーキテクチャにも適用される。Vimのコアプロセスと、VimのGUIプロセスは分離され、これもやはりstdin/stdoutを経由して、プロセス間のメッセージやりとりで動作する。

これはあくまでVimの大幅なリファクタリングであって、Vimのゼロからの再実装ではないし、VimをIDEへと変身させるようなものでもないという。

freenodeで#neovimが作られている。

2014-02-22

肉のハナマサのいい話

筆者は妖怪ハウスというシェアハウスで料理をしている。今住んでいるシェアハウスでは、住人と来客も合わせて、毎日3-5人ぐらいは食べる人がいる。料理というものは、大量に作ると効率的だ。また、食材も大量に買うと効率的だ。

そういうわけで、最近の食材の買い物は、もっぱら肉のハナマサで行っている。一気に大量に買えるので、効率的なのだ。しかも、うどんとか焼きそばとかソバの生麺の質は、近所の個人スーパーより、肉のハナマサのほうが一玉あたり安いうえ、質も上だ。もやしも2kgの袋で買うと、コストパフォーマンスが非常によい。最初は、もやしを2kgも使いきれるか心配だったが、もやしは色んな所に使いでがある。今住んでいるシェアハウスの住人は、とにかくたくさんたべるので、2kgのもやしであっても、数日もしないうちに使いきれてしまう。

というわけで、効率的な肉の華聖人はいえ、やはり新鮮な食材を常備するには、数日おきに行かなければならない。幸い、職場の近くにも肉のハナマサがあるので、帰りがけに買うこともできる。今住んでいるシェアハウスに近い肉のハナマサは、往復8kmほどかかるのだ。バスもあるそうだが、多少は運動がしたいので、歩いて買い物に出かけている。

さて、今日も肉のハナマサで大量に買い込んだが、うっかりと卵を割ってしまった。完全に筆者の責任で、10個入りの卵パックを3パック、カゴに入れて食材を物色していたところ、うっかりとかごを取り落としてしまったのだ。みると、パックあたり、2,3個の卵が割れてしまっている。やれやれ、失敗してしまった。これは、今日の夜は親子丼にでもするしかあるまいと思いながら、レジに行ったところ、なんと割れてない卵に取り替えてくれるという。完全に筆者の落ち度であると言ったのだが、それでも取り替えてもらった。

というわけで、筆者は割れていない卵パックを持って帰宅した。

肉のハナマサは偉大だ。

2014-02-19

アマゾンのお気に入りリストからドメモ

Amazon.co.jp: 江添亮: 江添のほしい物リストに入れておいたドメモが届いた。

ドメモというのは、とても簡単なゲームだ。誰でもすぐにルールを覚えることができ、とても白熱できる。1から7までの札があり、札は数字の数だけある、つまり、1の札は1枚あり、7の札は7枚ある。各プレイヤーが手札を取り、場にも公開された札と、伏せた札が置かれる。自分の手札は見えずに、相手の手札は全部見える。そして、見えざる自分の手札をあてていく。

このとき、札は書かれている数字の枚数だけあるということに注意する。例えば、7の札は7枚あるが、場に6枚しか見えなかったら、自分の所にあるか、伏せた札に入っているかだ。もし、7の札が3枚しか見えなければ、それは高確率で自分の手札にたくさん入っているということだ。

この、とてもわかりやすいルールは、全く知らない人に教えるのがとても簡単で、その場で突発的に始めるゲームとして、とても便利だ。しかも楽しい。

このようなわかりやすいゲームは、他にもいくつかある。例えば、 ダンジョンオブマンダム や、 Love Letterや、 藪の中 がある。

妖怪ハウスでは、今後もゲームを色々取り揃えておく予定だ。

2014-02-17

続アマゾンのお気に入りリスト

電気ケトルで沸かしたお湯でお茶を飲んでいると、今日もアマゾンから何かが送られてきた。何かと思えば、 YAMAHA(ヤマハ)ABS樹脂製リコーダー ソプラノ ジャーマン式 YRS-37IIIだった。

運指がジャーマン式なので、まだうまく吹けないが、一時間ほど練習して、The Free Software Songぐらいは吹けるようになった。

さて、今日の夜、風呂に入った後に、例の越中ふんどしを装備してみることにした。なかなか快適だ。ただし、色が赤であるのが気に食わない。江添亮: 江添のほしい物リストに白ふんどしを追加してみた。思いの外に快適なので、いずれ自分でも買うかも知れない。