Quantcast
Channel: 本の虫
Viewing all 1280 articles
Browse latest View live

git submoduleを含むレポジトリをGitHub Pagesで公開するときのsubmoduleのURLはhttpsでなければならない

$
0
0

江添亮の詳説C++17の出版記念の勉強会で使うスライド資料をGitHubにあげてGitHub Pagesで公開する作業をしていた。

歌舞伎座.tech 番外編「江添亮の詳説C++17」出版記念 - connpass

私はスライド資料の作成は、markdownで書き、pandocでreveal.js形式に変換し、reveal.jsでスライド形式で表示させている。いつもならばreveal.jsはリリース版のtarを展開してgit add .するのだが、今回は今まで使う機会のなかったgit submoduleを使おうと思った。man git submoduleしたところ使い方は簡単で、git submodule add URLするだけだ。

さっそくGitHubに上げてGitHub Pagesを有効にしたが、なぜか404、エラー内容を読むと、どうもGitHub Pagesのレポジトリでsubmoduleを使う場合は、URLはhttpsでなければならないそうだ。

Using submodules with Pages - User Documentation

まあ、たしかに理由はわかる。とはいえ、submodule先もgithubの場合、特別に対応することもできるのではないか。

submoduleのURLを後から書き換えるには、.gitsubmodulesを書き換えればよい。

https://github.com/EzoeRyou/slide-cpp17book


自宅のメインPCのストレージが故障した

$
0
0

江添亮の詳説C++17本の発売の余韻に浸る暇もなくC++入門書を書いているが、これがなかなか面倒だ。というのも、C++を学ぶ前にまず、C++のソースファイルをコンパイルして実行する方法を学ばなければならないと考えたので、環境構築から書いている。

具体的にはmkdirでディレクトリを作りcdで移動してそこにvimでテキストファイルを作成しGCCでコンパイルして実行するがカレントディレクトリはPATHに含まれていないので./を忘れずにつけるようになどといった、誰でも書けるような本当に初歩的な内容を書いている。

はたしてこんな初歩的な内容が必要なのかと疑問に思うこともあるが、しかし初心者がどこでつまづくかわからない以上、すべて書くしかない。すでにプログラミングを学んでいて実用的なソフトウェアを書いている人間であっても、今やプログラミング環境は多種多様になっており、CLIでの操作経験がまったくないままプログラマーとしてやっている人間がいても不思議ではない。したがって、カレントディレクトリはPATHに含まれないとか、コンパイルやリンクといった概念の説明が必要になる。

話は変わるが、今朝自宅のメイン環境として使っているラップトップの調子がとても悪かった。まずブートせずにbusyboxのシェルを表示する。fsckを書けたところブートするようにはなったが、何やら極端に遅い。dmesgするとストレージへのアクセスでエラーが大量に出ている。どうやらストレージが壊れたようだ。幸い、データはサルベージできたし、プログラマーの当然の嗜みとして参考書はgitで管理しており、常に複数のストレージに入れるようにしてあるので問題はなかったが、メインPCが使えないのは困ったものだ。自宅にはゲーム専用の不自由な日本語IMEすら無効化しているWindows PCとゴミのようなタブレットしかない。このタブレットはAMDの超省電力の非力なCPUを使っており、かつGPUがLinuxカーネルで使えないのでこともあろうかLLVMpipeでグラフィック表示している最悪の環境だ。

メインで使っていたラップトップは15インチで4Kディスプレイを内蔵していて、かつnVidiaのGPUを積んでいないという稀有な存在だ。AMDのGPUを積んでいるらしいのだがなぜかUbuntuでは認識されず、Intel HD Graphicsだけで動いている。訳あり中古で買った格安品で、訳ありの理由は、内蔵ディスプレイの中央あたりに白い常時点灯の線があるというものだ。地味につらいが値段は安く、4Kディスプレイを内蔵しているnVidiaのGPUを積んでいないコンピューターだったのでだましだまし使っていたのであった。

ストレージはHDDにキャッシュ用のそれなりの容量のフラッシュメモリがついているという、少し前に流行ったハイブリットHDDだ。ストレージさえ交換すれば再び使えるようになるのではないかとも思うが、残念ながらNVMe M.2 SSDとは違い、おそらくはラップトップ用のSATA接続の2.5インチHDDであろうし、調べたところ分解手順が一般人の分解を想定していないほど面倒だ。

早く自宅のメインPCを調達して自宅で参考書を執筆できる環境を整えなければならない。しかし思ったのだが、これはC++17本の印税の突っ込みどころとして最適ではないか。雀の涙のような印税ではあるが、高スペックなラップトップを一台買えるぐらいの額はある。それに経費と相殺すれば雑所得が確定申告が必要な額である20万円を下回るのではないか。ただ、調べると10万円を超え、かつ1年以上使うコンピューターについては減価償却という概念が出てきて、耐用年数が4年だそうだ。ただ、どうせ印税の額は少ないので4分の1にしても20万円を下回るのは容易いように思われる。ただ、それが執筆専用に使われない場合は比率を考えないといけないのでそれも難しい。

経費と税金のややこしい話はともかく、自宅に執筆用のPCが必要なので、さっそく久しぶりにラップトップを物色したが、どうにも難しい。私がほしいのは、15インチで4Kディスプレイ内蔵でnVidiaのGPUを積んでいないラップトップだ。私の本の執筆には高性能なGPUはいらないし、nVidiaのGPUは不自由なバイナリブロブのカーネルモジュールを必要とする。しかし、世の中には12インチで他の条件を満たすものか、15インチでnVidiaのGPUを積んでいるものしかない。

そして、ここ1,2年ぐらい顕著なのが、3K解像度のディスプレイだ。3200x1800程度の解像度のラップトップが増えている。これはけしからんことだ。作業効率というのは眼球にどれだけ多くのピクセルを叩き込めるかで決まるものだ。1920x1200が1920x1080に駆逐されたときも失望したのだが、4Kディスプレイの劣化版がHiDPIを名乗っているのもけしからん。3Kは劣化。4Kディスプレイは最低限の基準だ。

まあ、実際の理由は、4Kディスプレイ内蔵のラップトップはバッテリー駆動時間が短いので、HiDPIを謳いつつ電力消費を下げるために3K内蔵ディスプレイが出てきたのだろうし、15インチ4KディスプレイにnVidiaのGPUを積んだラップトップしかないというのも、15インチで4Kディスプレイを内蔵したラップトップにはGPU性能の需要もあるからそういう製品ばかりになっているのだろう。15インチで4Kディスプレイ内蔵でGPU性能はいらないという私の需要は少数派なのだろう。

というわけで、候補はSystem76かPurismか、あるいはDellのXPSあたりになる。System76は3K解像度、Purismは解像度も1920x1080しかない。Dellは無難だが、やはり15インチにはnVidiaのGPUがあり、13インチは3Kディスプレイだ。

2018 Jacksonville会議でC++のドラフト入りが決定した機能

$
0
0

2018 Jacksonville ISO C++ Committee Reddit Trip Report : cpp

なぜこのような情報をRedditで見なければならないのかという疑問はあるが、2018 Jacksonville会議の結果がRedditでまとめられている。

P0840R1: Language support for empty objects

[[no_unique_address]]属性が追加された。この属性はクラスの非staticサブオブジェクトがユニークなアドレスを必要としないとコンパイラーに支持するものだ。これによって、コンパイラーはそのサブオブジェクトにメモリレイアウト上でスペースを割り当てる必要がなくなるので、Empty Base Optimizationができる。

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

struct D
{
    [[no_unique_address]] A a ;
    [[no_unique_address]] B b ;
    [[no_unique_address]] C c ;
} ;

int main()
{
    // 1
    std::cout << sizeof(D) ;
}

例えばtraitsのようなクラスのサブオブジェクトとして持っておくのに使える。

template<typename Key, typename Value,
         typename Hash, typename Pred, typename Allocator>
class hash_map {
  [[no_unique_address]] Hash hasher;
  [[no_unique_address]] Pred pred;
  [[no_unique_address]] Allocator alloc;
  Bucket *buckets;
  // ...
public:
  // ...
};

P0634R2: Down with typename!

文脈上、型しか書けない場所に書かれたものは型であるとみなすことにより、依存名にtypenameを記述しなくてもすむように制限緩和する提案。

依存名が型である場合はtypenameキーワードによって型であることを明示しなければならない。


// Tはこんな感じの型を想定
struct example
{
    using type = int ;
    static constexpr type value = 0 ; 
} ;

// 
template < typename T >
typename T::type f()
{
    typename T::type x = T::value ;
    using type = typename T::type ;
    std::vector< typename T::type > v 
    return x ;
}

このコードが以下の様に書けるようになる。


template < typename T >
// typenameはいらない
T::type f()
{
    // typenameが必要
    typename T::type x = T::value ;
    // typenameはいらない
    using type = T::type ;
    // typenameはいらない
    std::vector< T::type > v 
    return x ;
}

書きやすくなった。

P0479R4: Proposed wording for likely and unlikely attributes (Revision 4)

[[likely]]と[[unlikely]]の追加。この属性は文に書くことができる。この属性が書かれた文を含む実行パスの実行の期待度を示す。

例えば以下のようなコードがあるとして、


while ( true )
{
    // まれにしか起こらないエラーのチェック
    if ( check_rare_error_condition() ) {
        // 分岐1
        // エラーへの対処
    } else {
        // 分岐2
        // 通常の処理
    }
}

このコードでは、エラーが起こることはまれであり、したがって分岐1が実行される可能性は低い。コンパイラーがその情報を事前に知っていれば、コード生成の際に役立てることができる。


    if ( check_rare_error_condition() )
    {
        [[unlikely]] ;
        // エラーへの対処
    }

この機能は大抵のコンパイラーが独自拡張として様々な文法ですでに実装している。

[PDF] P0754R1: version

ヘッダーファイル<version>を追加。このヘッダーファイルは標準規格的には何も入っていない。実装依存のバージョン番号やリリース番号を示す定義済みマクロを提供するためのヘッダーファイルだ。

多くのC++コンパイラーが独自の定義済みマクロでコンパイラーのバージョンその他の情報を提供している。問題は、そのような定義済みマクロは、コンパイラーマジックによって定義されるのでもなければ、なんらかの標準ライブラリのヘッダーファイルを読み込まないと定義されない。

そこで、標準ライブラリの中でも特に軽量なヘッダーファイルである<ciso646>が慣習的に使われてきたが、今回、ciso646は実用的な機能を提供していないので廃止しようという議論が持ち上がった。そこで、このヘッダーファイル自体に意味はないが、コンパイラー独自の定義済みマクロのためだけに#includeしている既存のコードがたくさんあるという指摘が上がった。

そのため、その用法をサポートするための最も軽量なヘッダーファイルである<version>が提案され、追加された。

P0355R5: Extending <chrono> to Calendars and Time Zones

<chrono>にカレンダーライブラリの追加。

int main()
{
    auto date = 2017y/mar/18d ;
    // "2018-03-18"
    std::cout << date ;
}

カレンダー操作が型安全に行える。

[PDF] P0753R1: placeholder

osyncstream用のバッファーフラッシュの動作を制御するマニピュレーターの追加。

[PDF] P0122R6: placeholder

連続したストレージを所有しないまま配列として扱うspanライブラリの追加。提案段階ではarray_refとかarray_viewなども提案されていたが、最終的にspanになった。

P0780R1: Pack expansion in lambda init-capture

ラムダ式の初期化キャプチャーでパック展開ができるようになった。これにより可変長テンプレートを使った関数テンプレートでラムダ式にパラメーターパックをそれぞれムーブキャプチャーすることができるようになった。

template < typename ... Types  >
void f( Types ... args )
{
    [ args = std::move(args)... ](){} ;
}

ドラフトの変更以外としては、simd<T>がParallerism TS v2に入ったり、Reflection TS v2, Library Fundamentals TS v3が発行されたりした。

現在の観測を見てみると、モジュールがC++20に入るかは疑わしい。コンセプトとレンジのコアは入りそうだ。

colony(歯抜けを許すvector)やflat_map(ソート済みvectorのバイナリサーチ)はC++20に入ってほしい。他には、fixed_capacity_vector(サイズ固定vector)やring_span(リングバッファー)

ドワンゴ広告

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

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

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

vectordash: 暗号通貨採掘している奴らに暗号通貨採掘よりは歩合のよい報酬を払ってGPGPU計算を購入するGPU版AirBnBみたいなサービス

$
0
0

Rent out your GPU compute to AI researchers and make ~2x more than mining the most profitable cryptocurrency. : gpumining

Deep Learningを研究しているある苦学生は、AWSやGoogle CloudのようなクラウドでGPGPU計算を提供している高い利用料に頭を悩ませていた。そこで、GeForce GTX 1080Tiを複数枚使ってEthereumを採掘している友人の存在に気が付き、交渉して、Ethereumを採掘するよりも歩合のよい報酬を支払い、機械学習に必要なGPGPU計算を請け負ってもらうことにした。その対価はEthereumを掘るよりは高いが、AWSやGoogle Cloudよりはよっぽど安い。

望みのGPGPU計算を終えてめでたしめでたしの苦学生はふと思う。「まてよ、世の中の暗号通貨採掘しているやつは、AI研究者に計算力を売ったほうが歩合がいいんじゃないのか」と。

そのような小規模なGPGPU計算力を売買するインフラは存在していなかったので、学生は自分で作り上げた。Vectordashだ。

Vectordash: GPU instances for deep learning

仕組みとしてはGPGPU計算力の売り主のコンピューターで実行されるコンテナーに買い主がsshしてGPGPU計算をして対価を支払うというものだ。

要するに、GPGPUのAirBnBみたいなものだ。

面白い仕組みだ。暗号通貨の採掘に計算力を注ぎ込んでも暗号通貨を維持する以上の価値はない。しかしこの方法では、計算力を直接販売できるし、暗号通貨採掘の利益より高いのであれば、売り手も買い手もWin-Winではないか。AWSやGoogle Cloudより安いとあればなおのことよい。

もちろん、すでに大勢の人間が指摘しているように、信頼という問題点がある。

売り主は本当に本物の計算力を提供しているのだろうか。特にGPGPU計算を売るというのが難しい。売り主に悪意があれば、カーネルに手を加え、GeForce GTX 1080を複数枚用意していると見せかけ、実際には何も計算せず、ランダムな結果を返すことができてしまう。結果は信頼できない。

たとえ売り主に悪意がないとしても、ハードウェアは故障する。コモディティハードウェアの信頼性は高くない。もしGPUが故障して間違った計算を行うが、見かけ上正常に動作しているように見える場合、結果は信頼できない。

計算力の売り主が信頼できない状態で計算結果の信頼性を担保したい場合、複数の売り主に同一の決定的(deterministic)な計算を依頼し、結果が同一であるかどうかを比較することで信頼度を上げることができる。しかし、そうすると利用料は数倍になり、AWSやGoogle Cloudに対して安いという魅力がなくなる。それに、完全に決定的(deterministic)な計算だけを扱うのも難しい。

買い主の悪意はどうだろうか。GPUはDMAできる。すると、買い主はDMAにより仮想化の檻を脱獄し、あまつさえルート権限を取得し、売り主のコンピューターをBOTネットワークの一部とするだろう。GPUに対するセキュアな仮想化技術はまだ発展途上だ。そして、セキュリティを担保するとパフォーマンスに影響を与えるだろう。

個人が計算力を提供する分散コンピューティングというのは前例のない話ではない。たとえばSETI@homeは宇宙からの観測データを有志が計算力を提供することにより知的な宇宙人の存在を発見しようという目的をもった分散コンピューティングだ。Folding@homeはタンパク質の折りたたみ構造を有志が計算力を提供することによって様々な疾患の治療に役立てようというものだ。

SETI@home

Folding@home

これらの既存の分散コンピューティングは、計算内容の提供者は固定で、参加はボランティアによるもので、しかも参加者に短期的な金銭による対価が支払われることはない。そのため、悪意ある計算力の提供者の存在や、計算内容に悪意があるリスクは低いと考えられる。

しかし、今回のvectordashとやらは、汎用的な計算力の売買を行うので、悪意の可能性は大いに考慮しなければならない。

問題はあるものの、暗号通貨に計算力と電力を注ぎ込むよりは、よほど人類にとって有益な計算力市場が出来上がるのではないか。

入門書の文章量が増える問題

$
0
0

C++17の参考書を書き終えた今、この世に必要なのはC++の入門書だ。そこでC++の入門書を苦しみながら書いているのだが、一つ問題がある。文章量が多いということだ。

今書いているC++の入門書は、まだ本の序盤までしか書いていない。C++のソースコードのコンパイルと実行方法、ビルドシステム、そしてようやく条件分岐を半分ぐらい書いた。後は付録としてプリプロセッサーを解説した。その程度だ。

しかし、wcで現行を単一のHTMLファイルに変換した結果を大雑把に計算すると、今書きかけのC++入門書が"2335 7876 178578"に対し、完成したC++17本が"8280 31208 639671"だ。まだ条件分岐までしか書いてないというのに少し分量が多くないだろうか。

考えてみると、文章量が多くなるのも無理はない話だ。初心者の気持ちに寄り添って書いている結果、「整数と浮動小数点数を演算すると結果は浮動小数点数になる」と書けば済む程度のところを、

  1. 整数と浮動小数点数を演算するとどうなるのだろうか?
  2. 確かめてみよう。
  3. ソースコード
  4. 実行結果
  5. なるほど、整数と浮動小数点数を演算すると浮動小数点数になることがわかる

などという冗長な書き方をしているためだ。これでは文章量が増えるのも当然だ。

しかし、冗長ではない書き方をするとなると、結果的にリファレンスマニュアルのような無味乾燥とした記述が続く。それで入門できる人間は、規格書とか私が昔書いたC++11/14コア言語を読めばC++を学べるはずだ。

とはいえ、文章量が多いとそれだけ読むのに労力がかかり、ただでさえ人間の脳に負担を強いる全く新しいプログラミング言語の習得に、長文を読むという追加の負担を強いることになる。

この問題をどうすればいいのだろう。Bjarne StroustrupのC++入門書があまりにも長大で鈍重で悪書の見本のような参考書であるとかつてあざ笑ったが、これは笑えない由々しき問題だ。このペースで書き続けると鈍器として凶器転用可能な重量を持つ入門書ができあがってしまう。

ドワンゴ広告

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

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

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

江添ボドゲ会@4月15日

ロシア、Telegramをブロックするために180万ものIPアドレスをブロック

$
0
0

Russia Bans 1.8 Million Amazon and Google IPs in Attempt to Block Telegram

ロシアはインスタントメッセージングサービスのTelegramをブロックするため、AmazonやGoogleの所有する約180万ものIPアドレスをブロックした。

以下がそのIPアドレスの範囲で、1835008個のIPアドレスになる。


52.58.0.0/15
18.196.0.0/15
18.194.0.0/15
18.184.0.0/15
35.156.0.0/14
35.192.0.0/12

Telegramの創始者は以下のような声明を出したそうだ。

Telegram: Contact @durov

過去24時間でTelegramはロシアのISPによってBANされた。理由は我々が暗号鍵をロシアの諜報機関に提出するのを拒んだためだ。我々にとってこれは容易い選択であった。我々は顧客に対し100%のプライバシーを約束しており、約束を守れぬのであればむしろ消えるべきであるからだ。」

BANにもかかわらず、ユーザーの利用率は極端に落ちていない。これはロシア人は政府の検閲に対抗するために日常的にVPNやプロクシーを使っているためである。また我々はサードパーティのクラウドプロクシーサービスを使うことで部分的にユーザーにサービスを提供し続けている。

ロシアのTelegramユーザーの皆さんの協力に感謝する。また政治的検閲に与しなかったApple, Google, Amazon, Microsoftにも感謝する。

ロシアはTelegramユーザーの7%を占めている。ロシア市場を失ったとしても、他の地域でのユーザーの増加がこの穴を数ヶ月以内に埋めるであろう。しかし、ロシアのユーザーにサービスを提供し続けることは個人的にも重要だ。

ロシアとその他の地域におけるインターネットの自由を守るために、私はsocks5プロクシーとVPNを提供する個人や団体にbitcoinを寄付することにした。私はこの運動のために今年数百万ドルを喜んで寄付するし、私に続く者が出てきてほしい。私はこれをデジタル抵抗軍を呼ぶ。電磁的自由とその進展に対する草の根活動だ。

一方、日本では出版社が両手を上げて、緊急避難によるIPアドレスのブロックに賛同している。日本もロシアや中国と同じ道を辿りつつある。隷属への道は近い。

2018-04でC++のドラフトに入った変更

$
0
0

C++のドラフトが更新されている。最新版はN4741だ。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4741.pdf

変更点はEditor's Reportに書いてある。

N4740: N4740 Editors' Report -- Programming Languages -- C++

今回入った主要な変更は以下の通り。

P0840R2: Language support for empty objects

[[no_unique_address]]属性の追加。

この属性は、クラスが状態を持たずクラスを表現するためにストレージを割り当てなくてもよいことを意味する。

クラスには、存在すること自体に意味があり、そのオブジェクトに特に意味はないクラスがある。


template<typename Key, typename Value,
         typename Hash, typename Pred, typename Allocator>
class hash_map {
  Hash hasher;
  Pred pred;
  Allocator alloc;
  // ...
public:
  // ...
};

このようなコードで、HashやPredやAllocatorといったクラスが状態を持たないもののみを使用可能だと取り決めた場合、ストレージを割り当てる必要がない。しかし、このような基本クラスや非staticデータメンバーであっても、アドレス可能にするために最低でも1バイトはストレージを割り当てる必要がある。

[[no_unique_address]]はこのようなストレージの確保を必要としない、アドレスを取る必要がない型に使うことで、不必要なストレージの割当を回避することができる。


template<typename Key, typename Value,
         typename Hash, typename Pred, typename Allocator>
class hash_map {
  [[no_unique_address]] Hash hasher;
  [[no_unique_address]] Pred pred;
  [[no_unique_address]] Allocator alloc;
  // ...
public:
  // ...
};

P0962R1: Relaxing the range-for loop customization point finding rules

range-based forはメンバー関数begin/endのいずれか片方を持っている場合は、ADLによるbegin/endの検索を行わない。しかし、たまたまクラスがbegin/endという名前の片方のメンバー関数だけを持っていた場合も、ADLによる検索が行われない。

range-base forはbegin/end両方のメンバー関数を持つ場合のみADLによる検索を行わないようにする変更。

当然の話だ。

[PDF] P0969R0: Allow structured bindings to accessible members

クラスを構造化束縛する場合、メンバーはpublicでなければならないとされている。


class Three
{
    int a, b, c ;
} ;

void f()
{
    Three t{1,2,3} ;
    auto [a,b,c] = t ; // エラー
}

しかしこれはおかしな話だ。というのも、アクセス指定というのは使った文脈が重要だからだ。


class Three
{
    int a, b, c ;
    friend void f() ;
public :
    Three( int a, int b, int c )
        : a(a), b(b), c(c) { }
} ;

void f()
{
    Three t{1,2,3} ;
    // エラー、friendなのに
    auto [a,b,c] = t ; 
}

構造化束縛でpublicなメンバーに限らず、アクセスできる場所ではアクセスできるようにする変更。

当然すぎる。

P0961R1: Relaxing the structured bindings customization point finding rules

構造化束縛でメンバー関数getが見つかったときに、テンプレートではない場合は、ADLで検索する機能。

これも当然だ。

P0634R3: Down with typename!

文脈上型であることが明らかな場所では依存名にtypenameを付けなくても良くする機能。

template < typename T >
using type = typename T::type ;

と書くかわりに、

template < typename T >
using type = T::type ;

と書ける。他にも様々な文脈上型しか書けない場所でtypenameを省略できる。

P0780R2: Pack expansion in lambda init-capture

ラムダ式の初期化キャプチャーの中でパック展開できる機能。

たとえば、パラメーターパックをstd::moveしつつパック展開して初期化キャプチャーするには以下のように書ける。

template < typename ... Types  >
void f( Types & ... args )
{
    [ ... args = std::move(args) ]
    (){ } ;
}

P0479R5: Proposed wording for likely and unlikely attributes (Revision 5)

分岐先の実行されやすさを指示できる[[likely]], [[unlikely]]属性の追加。

ある分岐先が実行されやすい時、あるいは実行されにくいときがコンパイル時にわかっているときは、その情報をコンパイラーにヒントとして伝えることで、コンパイラーは実行されやすいコードをよりキャッシュに乗りやすいホットな領域に配置したり、コード生成を工夫したりといった最適化ができる。


// めったに起こらないエラーの確認
if ( check_uncommon_error() )
{
    [[unlikely]] ;
    // エラー時の処理
}

// 必ず成功するはずの初歩的なチェック
if ( sanity_check() )
{
    [[likely] ;
    // 通常の処理
}

P0905R1: Symmetry for spaceship

比較演算子としてoperator <=>が追加されたが、"a <=> b"が合法であるならば、"b <=> a"も合法であり、かつその結果も自然なものになるように規定する変更。

[PDF] P0754R2: version

何もしないヘッダーファイル<version>の追加。このヘッダーファイルはコンパイラーによって定義される実装依存の定義済みマクロなどを定義ささせるのに使われる。そのような定義済みマクロを使うには、何らかの標準ヘッダーを#includeしなければならず、そのような軽量ヘッダーとして追加された。

P0355R7: Extending to Calendars and Time Zones

<chrono>にカレンダー機能を追加する。ユーザー定義リテラルによりコード中でも読みやすくなる。

int main()
{
    auto date = 2018y/April/18 ;

    // 2018-04-18
    std::cout << date << "\n" ;

    // 2018-04-19
    date += 1 ;
    std::cout << date << "\n" ;
    
    // 2018-03-25
    date -= 25 ;
    std::cout << date << "\n" ;
    
}

日付処理が簡単にできるようになる。

[PDF] P0122R7: span : bounds - safe views for sequences of objects

spanライブラリの追加。これは連続したストレージ上の配列を扱うストレージを所有しないライブラリだ。


C++入門書で再帰について解説しようとしたら思わぬ最適化できないコードに出くわした

$
0
0

C++入門書を書き始めて早数カ月、すでに文章量が「江添亮の詳説C++17」の半分近くに達しているが、まだようやくループを説明したところだ。

ループの章を一通り書き終えて、ついでに再帰によってループを実現する方法について軽く触れて章を閉じようと、以下のようなコードを書いた。

void hello()
{
    std::cout << "hello\n"s ;
    hello() ;
}

すると何故かsegmentation faultを起こすではないか。GCCでもClangでも同じ挙動になる。なぜC++コンパイラーはこの程度の末尾再帰を最適化できないのだろうか。

不思議に思って以下のコードも試すと、こちらは問題なく末尾再帰の最適化が行われる。

void hello()
{
    std::cout << "hello\n" ;
    hello() ;
}

違いは文字列だ。今回の入門書では、初心者に簡単にするために、文字列はすべてstd::stringを返すユーザー定義リテラルのoperator "" sを使っているのだ。これにより初心者は、"hello\n"sとかけばstd::stringとして使える。つまり、

auto s = "hello"s ;
s.size() ;

などと書ける。難しいことを一切考えなくてもよい。わたしの本が書き上がって出版されるまでにまだ1年はかかるだろうし、その頃にはC++17が普及している。C++17を使って初心者でも学びやすい記述をすることで、私のC++入門書は初心者にも優しい本になるだろう。そう考えていた矢先に何ということだ。

どうもstd::stringがあると末尾再帰の最適化が行われないらしい。しかしおかしい。一時オブジェクトの寿命はリファレンスにより寿命延長されない場合はfull-expressionの中までのはずだ。したがってこのコードはまだ末尾再帰のはずだ。再帰呼び出し後に何かする必要は何もないはずだ。

不思議に思って以下のコードを試してみたが、やはり末尾再帰の最適化はされていない。

void hello()
{
    {
        std::string s = "hello\n" ;
        std::cout << s ;
    }
    hello() ;
}

これなら一時オブジェクトでもないしブロックスコープを明示的に使っているし問題はないだろうと思ったが、なぜかコンパイラーは末尾再帰の最適化を諦めてしまう。

では関数で包んでしまうというのはどうか。

void hello()
{
    []{ std::cout << "hello\n"s ; }() ;
    hello() ;
}

これはうまくいった。関数で包んだ場合、コンパイラーは末尾再帰を最適化する。

コンパイラーの気持ちはよくわからない。

LLVMで5番目に貢献の多い開発者、LLVMの最近のSJW運動に反対して開発をやめると表明

$
0
0

One Of LLVM's Top Contributors Quits Development Over CoC, Outreach Program - Phoronix

[llvm-dev] I am leaving llvm

Rafael Avila de Espindolaは2006年からLLVMに対して4300以上もコミットした開発者で、現在LLVMの全Authorの中で第5位のコミット数を保有する開発者である。Rafaelは最近のLLVM Code of Conductと今年のアウトリーチプログラムへの参加を、「社会不正義」(Social Injustice)だと吐き捨ててLLVMの開発をやめる声明を出した。

LLVMのCode of Conductは以下の通り。

LLVM Community Code of Conduct — LLVM 7 documentation

  • 仲良く辛抱強くやれよ
  • 新参は歓迎しろよ
  • 迷惑かけんなよ
  • 尊敬しろよ
  • 言葉遣いには気をつけるのと、あと親切にしてやれよ

Code of Conductは、過去に様々な自由ソフトウェアコミュニティが取り入れて、その結果政治的な問題を引き起こしてきた歴史がある規約だ。そもそも存在自体が政治であるものを入れると純粋な技術から遠ざかり、些細な言葉遣いのような揚げ足取りの政治に終始するのは当然であると言えよう。

アウトリーチプログラムというのは現在コミュニティでマイノリティである属性を持った開発者を新規に確保するための優遇措置だ。属性というのは主に性別で、具体的には女性のことだ。しかしこれは純粋な技術力ではない性別のような条件で人を優遇するということであり、これはまさに性差別そのものである。これをやりだすと人物が純粋な技術力で評価されず、たまたまマイノリティの性や宗教や門地のような属性を持っていたというだけで優遇される。

私がさる理由はコミュニティの変化のためだ。現在のライセンス変更の議論は私がGCCの開発をしていた頃の自由ソフトウェア財団の政治を彷彿とさせるものがある。これだけではまだ去るほどの理由ではない。コードと同じように、LLVMはまだ最適なライセンスを選択しているし、コミュニティの変化というのがライセンスの変更だけであれば、まだ続けることもできた。

私が受け入れられないコミュニティの変化は社会不正義運動がはびこっていることだ。私がLLVMに参加したとき、誰も私の宗教や政治信条について疑問を呈するものはいなかった。我々は皆、良きコンパイラーフレームワークを作ることに注力していた。

ここ最近、Code of Conductやらが採用された。これによれば、コミュニティはすべての「政治信条」を歓迎するよう務めるとある。しかし、Code of Conductの存在に反対する政治信条を持つ者は歓迎できない。そして、カンファレンスに参加するにはCode of Conductへの同意が必要であるからして、私はもはや参加することができなくなった。

トドメの一撃は、LLVMがある団体と手を組んだことで、この団体は公に性別や門地による差別を行っている。これは私の倫理と真っ向から対立するものであり、私はこの手の輩と一緒くたにされないために、プロジェクトを去る必要がある。

RafaelのMLへの投稿は、最後に"So long, and thanks for all the bugs,"(さよなら、いままでバグをたくさんありがとう)と締めくくっている。銀河ヒッチハイクガイドへのリファレンスのようだ。

glibcのabortマニュアルの中絶方針ジョークについて

$
0
0

Who controls glibc? [LWN.net]

「glibcのabortのマニュアルにはabort(終了)とabortion(中絶)をかけた中絶ジョークがあり、これはマニュアルとして有益ではなくて混乱の元なので削除するというパッチが提出され、受け入れられたが、RMSの反対により差し戻された」

これだけ読むとくだらない出来事のように思えるし、人によってはこのジョークの存在が好ましくないとか下品だと思うかもしれない。しかし、これは単に下品なジョークで片付けてよい問題ではない。実は音はもっと深いのだ。

まず、ジョークの内容は中絶ジョークではなく、中絶方針ジョークなのだ。

glibcのabortのマニュアルには以下の記載がある。

将来の変更警告:連邦検閲規制委員会に提案された方針によれば、この関数を呼び出すことができる可能性についての情報を我々が与えることが禁止されるかもしれない。我々はこれがプログラムを終了する適切な方法ではないと言わざるを得なくなるかもしれない。

問題の方針とは、メキシコシティポリシーと呼ばれているアメリカ合衆国では歴史の深いものだ。

Mexico City policy - Wikipedia

メキシコシティポリシーとはアメリカ合衆国政府の方針で外国籍のNGOがアメリカ政府から出資、健康補助、HIV補助、妊婦及び子供の補助を受ける場合「中絶の実施、並びに中絶を家族計画の方法として積極的に宣伝する」ことをしてはならない、というものだ。

これはアメリカ合衆国で中絶の違憲判決が出ていなかった時代から続く方針だ。歴史的に右翼である共和党はこの方針を肯定し、左翼である民主党は否定している。アメリカ合衆国における右翼とはキリスト教原理主義者を指し中絶は違法であるとの立場を取る。左翼はリベラルであり中絶は合法であるとの立場を取る。

メキシコシティポリシーの名前は1984年に共和党のロナルド・レーガン政権が名付けたものだ。これは1993年に民主党のビル・クリントン政権で撤回されたが、2001年に共和党のジョージ・W・ブッシュ政権で復活し、2009年に民主党のバラク・オバマ政権で撤回され、そして当然、2017年の共和党のドナルド・トランプ政権では復活した。

ちなみに、ブッシュ政権のときにメキシコシティポリシーの違憲性を問う訴訟で、アメリカ政府が外国籍のNGOを補助するときに中絶への立場を考慮することは違憲ではないという判決が出ている。

さて、話をglibcに戻そう。glibcというのはGNUであり自由ソフトウェア財団である。RMSが始めたGNUはその当初から左翼主義が全面的に出ており、ソフトウェア開発は政治活動だと考えている。その思想に基づけば、この20年前からマニュアルに存在する中絶方針ジョークは必要不可欠でありたやすく取り除いてはならないものである。

今回はRMSが強権を発動し、ジョークは残った。

この問題の背景事情を考えるに、私はこの中絶方針ジョークは残すべきであると思う。

Intelの古いマニュアルを誤読したために生じた脆弱性

$
0
0

Multiple OS Vendors Release Security Patches After Misinterpreting Intel Docs

Multiple OS Vendors Release Security Patches After Misinterpreting Intel Docs | Hacker News

8086でスタックを切り替えるには、ssレジスターとspレジスターを両方変更する必要がある。しかし、ssレジスターだけを変更してまだspレジスターを変更していないときに割り込みがかかると問題だ。そこで、8086は粋なはからいによって例外的にこの問題に対処した。ssレジスターを変更した直後の1命令では割り込みが発生しない。仮に割り込みが起きたとしても1命令を実行するまでは遅延される。

もし、ssレジスターを書き換えた直後の1命令でカーネルモードに入った場合、この粋なはからいが問題になる。カーネルモードに入ったあと、カーネルコードを1命令たりとも実行していない段階で割り込みが発生する可能性があるからだ。しかも実行はカーネルモードだ。

OpenBSD、1985年に追加されたIntelの最新の誇大広告された機能を使わないことにより脆弱性を華麗に回避

$
0
0

“We didn't chase the fad of using every Intel CPU feature” | Hacker News

'Re: CVE-2018-8897' - MARC

前回の記事であるIntelの古いマニュアルを誤読したために生じた脆弱性では、IntelのCPUがスタック切り替えるためにss/spレジスターをアトミックに更新する汚いハックとして、ssレジスターが変更された直後の1命令は割り込みが遅延される古い仕様があるが、多くのOSはこの古い仕様を把握していなかったため、ssレジスターを変更した直後の1命令でカーネルモードに入り、かつハードウェアブレイクポイントが設定されたことにより割り込みを起こせば、カーネルモードに入った直後にカーネルのコードを1命令たりとも実行していない状況でカーネルモードとしてユーザーの割り込みが実行される脆弱性を引き起こしていた。

さて、各OSが対応に追われるなか、セキュリティに万全の体制を取ることで定評のあるOpenBSDでは特に何事もなくのほほんとしているので、MLにこのことについて質問をするものがいた。

OpenBSDが影響を受けないという理由について教えてほしいんですけど?

バカな質問ですみませんが、このFreeBSDもこの問題に引っかかっているのに、なぜOpenBSDは平気なのか不思議です。

事前に把握してたんですか?

昨日、一面記事になったような大ニュースになぜOpenBSDは引っかかっていなかったのか気になります。

これに対するTheo De Raadtの返事。

Intelの誇大広告まみれのCPU機能を全部追いかけるようなマネはしていないんでな。

We didn't chase the fad of using every Intel cpu feature.

強すぎる。

この機能というのはi386から追加されたハードウェアブレイクポイント機能のことだ。なんとOpenBSDではユーザースペースからx86のハードウェアブレイクポイント機能の使用を許可していない。ではgdbのようなユーザースペースのデバッガーはどうやってブレイクポイントを実装しているのかと言うと、古き良きソフトウェア実装を用いている。ブレイクポイントを仕掛けたい部分のコードを割り込み命令(int 3とか)とか無効命令(ゼロ除算)で置き換えておき、例外割り込みをブレイクポイントを仕掛けたい場所で発生させることによる移植性の高いソフトウェア実装だ。

ちなみに、IntelのCPUがハードウェアブレイクポイント機能を実装したのは1985年のi386にまで遡ることができる。

結果として、OpenBSDは今回の主要なOSが軒並み影響を受けた問題に対して何の影響も受けていないので、結果的に正しかったと言えるが、いやしかし凄まじい。OpenBSDのセキュリティにかける情熱を過小評価していた。

ポルノ本意制の通貨が登場したことにより今後予想される問題について

$
0
0

ポルノ動画サイトの最大手であるポルノハブが仮想通貨Vergeによる支払いを受け付けているそうだ。

世界最大のポルノサイトが仮想通貨「verge」に対応、アクセスしてみるとびっくり! ポルノ業界が急激に進化中!

これはとても面白い事象である。というのも、この通貨はポルノと交換できることがポルノハブによって保証されているわけだ。すなわち、これは金本位制ならぬポルノ本位制である。しかもこの話は単なる空想に終わらない。ポルノハブは実際にこの通貨とポルノの交換を行っているわけで実態がある。ここにポルノ本位制の通貨が登場した。

ポルノ本位制の通貨が存在する社会はどのように変革していくのか、ポルノ本意制の通貨を使うときには何に気をつければよいのか。我々人類は通貨と経済学について長い歴史があるので、歴史から学ぶことで今後の動向は予測できる。本記事ではポルノ本位制の通貨がもたらすシュールな世界を紹介しよう。

ある通貨はポルノと交換できることが保証されているとして、一体どのようなポルノと交換できるのだろうか。ポルノはどのようなものであってもポルノであり、したがってポルノとしての価値を持つはずだ。質の高いポルノを生産するのにはコストがかかる。すると、世の中には質の悪い製造が容易なポルノが量産されるだろう。通貨と交換品の価値に差が生じた場合、人々は通貨と交換するポルノには質の悪いポルノを使い、質の良いポルノは貯蓄するようになる。これを「悪ポルノは良ポルノを駆逐する」といい、グレシャムの法則とも呼ばれている。

経済学的にポルノの価値を考えると興味深い事情がある。ポルノの価値はまだ誰も見たことのない市場に出回っていない新作ほど高い。みんな見たような市場に出回りすぎたポルノは価値が低い。これを考えると、ポルノは金のように価値が安定しておらず、消費財である。しかし金の生産量は簡単に増やせないが、ポルノの生産量は裸の人間とカメラさえあればいくらでも生産できる。しかも一人の人間に複数のカメラを使うことで並列生産も可能だ。中には車とドラゴンをポルノだとみなす人もいるが、ドラゴンの用意はやや難しい。最近は地図上にもドラゴンの住まう地と書かれる土地が少なくなったからだ。

ポルノ本意制の社会では、実経済に出回っている通貨がいつポルノとの交換を要求されるかわからない。そこで、銀行は十分な量の価値の高い未公開ポルノを戦略的に備蓄しておく。これを準備ポルノという。

なぜ実経済が存在するポルノより多い通貨を動かすようになるのだろうか。それは借金の存在のためだ。まだポルノを所有していない人間が、将来ポルノを所有する信用によって通貨を借りる。その通貨でポルノを生産し、借金を返す。このとき、生産したポルノによって借金以上の価値が生まれれば得をする。ところで、借金をしたときまだポルノは世の中に存在していなかったわけだ。しかし借金をしなければポルノは生産されなかった。したがって、実経済では常に準備ポルノ以上の通貨が動いているのだ。

現実には、市場に出回る通貨すべてを一斉に換ポルノしたときの需要を満たすほどの準備ポルノを用意することはできないだろう。皆が一斉に通貨とポルノ交換、すなわち換ポルノを要求したとき、取り付け騒ぎが起き市場が混乱する。このような取り付け騒ぎはめったに起こらないが、たまに些細な噂が拡大解釈されて発生することがある。例えば女子高生が何気なくつぶやいた、「最近ポルノハブ危ないんだって」という言葉からポルノの取り付け騒ぎが発生し、準備ポルノの少なかった弱小ポルノサイトが閉鎖に追い込まれることは十分にあるだろう。そのような自体に陥った場合、まず自殺したと噂される理事長自ら生存を主張し、巨大スクリーンでポルノを映すことにより準備ポルノは十分にあることをアピールすべきだ。

不況時には、ポルノが十分に国内に供給されない。このとき、国内にすらポルノ供給が足りていないのに海外にポルノを輸出するのはけしからんという極めて素朴で単純な考え方が国民に芽生え、そのような狭い思想の政治家が当選する。結果として、国家はお互いにポルノ輸出を禁ずるようになり、各国が経済的に鎖国し始める。

こうしたことから、ポルノ本意制はいずれ破綻し、廃止しなければならなくなるだろう。どうやって廃止するのかを歴史に学んで今から対策しておこう。国家は通貨とポルノの法定為替を一方的に定め、国民の所有するポルノ財産をすべて法定為替で強制的に買い上げるかもしれない。

そして、今と同じようにポルノと通貨は変動為替に移行し、取引所に直結したアルゴリズムトレード勢がマイクロ秒単位でポルノ価値を判断して先物取引をするようになるだろう。

他にも面白い思考実験として、フィクションの世界では水本位制がある。これはFalloutというゲームの世界の設定だ。全面核戦争の後に清潔な飲料水が貴重になり水が価値になった。しかし水を持ち運ぶのは手間なので、ある有力な水商人が水とボトルキャップを交換するようになった。なぜボトルキャップなのかと言うと、もはやボトルキャップを製造する技術や設備は存在しないからだ。つまり、ボトルキャップは偽造が実質不可能で、全面核戦争前に製造されたものしか残っていない。偽造が不可能であれば貨幣として使うには十分だ。

世の中にはプログラミングを理解できない人間が存在する

$
0
0

現在、C++によるプログラミングの入門書を書いているので、初心者のプログラミングの学習過程にとても興味がある。私自身も初心者の気持ちを取り戻すためにHaskellを学んでみた。最初の数日は頭が痛くなるほど難しかったが、そこを過ぎてみれば後は楽になってしまった。結局、初心者の気持ちはあまりわからなかった。結局、プログラミングの基礎はすでに学んでしまっているので、

先日、FizzBuzzがわからないから教えてくれという知人がいたので、これは初心者の気持ちを知るいい機会と話を聞いてみたところ、想像を絶する世界が見えてきた。

まずこれが動かないと悩んでいたコードだ。


for ( int i = 0 ; i <= 100 ; i++ )
{
}
else if ( i % 15 == 0 )
{
    Debug.log("FizzBuzz") ;
}
else if ( i % 3 == 0 )
{
    Debug.log("Fizz") ;
}
else if ( i % 5 == 0 )
{
    Debug.log("Buzz") ;
}
else
{
    Debug.log(i) ;
}

一見するとそれらしいソースコードのようにみえるが、そもそも文法が間違っている。文法が間違っている箇所を指差しても納得しない。for文の文法を説明しようとするが聞く耳を持たない。「これが間違っているなら参考にしている教科書も間違っている」との一点張りで誤りが存在していることを頑なに認めない。参考にしているらしいスライド資料にのっているコード例と比較させても間違いの箇所を判断できない。for文の文法の説明をもう一度試みるがやはり聞く耳を持たない。

そしてソースコードの見た目を適当に書き換えてなんとか問題を「修正」しようと試みる。私はいつシェイクスピアの名作が出来上がるだろうかと考えながらその様子を見守っていた。

ややあって、奇跡的にソースコードが適切な形に「修正」された。しかし出力は期待通りにならない。当然だ。なぜならこれはUnityで、使っているのはデバッグログ用の機能であって、重複は省かれるからだ。出力は、1, 2, "Fizz"というメッセージが何件, 4, "Buzz"というメッセージが何件, 7, 8...と続く

そもそも基礎的なプログラミングの知識が十分ではないのだから、Unityはやめてもっと罠の少ないCLI環境でプログラミングの基礎を学ぶべきだと諭しても、「Unityは私がやりたいことを実現できる環境であり私のモチベ維持のために重要であるからUnityでやる」といって改めようとしない。

これは一体どうすればいいのだろう。こういう人間は教育不可能だ。この人物の経歴を見るに、どうもそれらしく見えるモックアップをでっち上げてきたアート系の人間のようだ。本人は今の時代は科学とアートは同じものでありアートを融合することでユーザービリティを考慮したUIが云々などと、まるでピタゴラス派のようなことを言う。世界は人間にとって美しい数字とか法則で定義されるべきであり、定義が観測結果に従わないとしても定義は正しいと主張したのがピタゴラス派だ。アートに引きこもっているならそれでいいのだが、それは科学ではない。コンパイラーのソースコードの解釈はこの自然界には珍しいことに冪等性を持っているのだから、見た目をでっち上げるのではなくて本質を理解すべきなのだ。たとえその本質が自分の美学に合わなかったとしてもだ。私は本棚にあったアラン・ソーカルの著書、知の欺瞞を手に取らせてみたが、あまり興味は示さなかったようだ。

こういう人間によって書かれたソースコードは一見もっともらしく見えるが、文法違反の間違ったコードとなる。どこかからか発見してきたコードをコピペしてツギハギしてそれらしい見た目のソースコードをでっち上げる。人間相手であれば、いかにも主題について理解したかのようにもっともらしくでっち上げた小論文を書いて読ませれば筆者は主題を理解していると読者を騙すことは可能だが、ことコンパイラーが相手では文法違反のソースコードを騙すことなどできない。

思うに、先天的に、あるいは幼少期の教育の結果、プログラミングに向かない学習方法に最適化されてしまった人間がいるのではないだろうか。物事の本質を完全に理解するにはコストがかかる。しかし、不完全な理解だがそれらしいものをでっち上げるにはコストがかからない。そして、人間には、それらしくでっち上げられた偽物と、本質を理解した上で作られた本物を判別するのが難しい。一方コンピューターは違う。コンパイラーはソースコードがいかに本物のソースコードらしい見た目をしていようとも、文法違反のソースコードを判別できる。コストを書けずに結果を出すためにそれらしくでっち上げる学習方法に最適化されてしまった人間は、コンパイラーに対して、それらしくでっち上げられたソースコードを食わせてコンパイラーが騙されてくれることを期待する。しかしコンピューターは騙されない。そもそも騙しようがない。コンパイラーは定義済みの規則に則って判断するだけで騙すという概念すらないのだから。


江添ボドゲ会@6月10日

coinhiveが不正であるというナンセンスについて

$
0
0

coinhiveの設置者が不正指令電磁的記録取得・保管罪で略式起訴を受けたので正式に裁判して争う発表をした。

仮想通貨マイニング(Coinhive)で家宅捜索を受けた話 - Webを楽しもう「ドークツ」

高木浩光@自宅の日記 - 懸念されていた濫用がついに始まった刑法19章の2「不正指令電磁的記録に関する罪」

6月10日の高木宏光の記事では具体性がなかったのでよくわからなかったのだが、こうして具体例を目にしてみるとこの件がとてもひどいことがわかる。

裁判は多少のカネと時間がかかるがそれほど労力はかからない。数カ月に一度、提出した書類道理の陳述するという儀式をするだけのものだ。みんなもっと積極的に裁判をすべきだ。

法律の解釈は裁判をして判例を作ることで成り立っているので、おかしいと思った法律解釈には積極的に裁判をしないとどんどん悪い判例が積もっていく。

それはそれとしてcoinhiveは嫌いなので広告と同じくブラウザー拡張でブロックするべきだ。

xkcd: お客様特典

$
0
0

xkcd: Customer Rewards

23ドル3セントになります。

ところで、あなたの本名を教えていただけるのならば24セントお支払いたします。家族構成を教えていただけるのであれば35セント、電話番号に79セント、あなたのスマフォをこの場で貸していただいてあなたのFacebookの投稿一覧を確認させてもらえるのであれば1ドル20セントお支払します。

ポイントカードと特典は、独立した取引として考えた場合、とても奇妙なものになる。

title="うちの製品をSNSに投稿していただけるのであれば1ドル47セント、グループチャットで毎回話題に持ち出すのであれば2ドル5セント、運転中にうちの広告を通過した場合乗員一人に付き11セントお支払します。"

そういえばレシートを1枚10円で買い取るサービスが流行っているようだ。

プログラミング入門書の執筆という手探りの活動

$
0
0

ここ最近、まともにブログを書けていない。最新のC++の提案も追えていない。それもこれも、C++によるプログラミングの入門書を書いているためだ。

およそプログラミングが個人でもできるようになって何十年もたとうとしているのだから、いい加減にプログラミングの入門書を書くお作法が成立しても良さそうなものだが、そういった定石は一向に確立されていない。名著と呼ばれる入門書は何冊もあるが、どれもその時代に特化した記述をしていて、その構成を模倣しても現代の入門書としては不適切だ。

結果として、入門書の執筆は自分の感性を信じつつ手探りで書き進めることになる。

よくC++の教育において批判されるのは、ポインターや配列といった低級な要素を最初に教える時代錯誤な点だ。たしかに、現代のC++はポインターや配列を使わなくても書ける。しかし、アドレスやメモリ上の連続したオブジェクトといった概念を理解しないまま優秀なコードが書けるだろうか。ポインターはアドレスを扱うには文法上の罠が多く、配列もメモリ上の連続したオブジェクトを扱うには文法上の罠が多い。

今書いているC++の入門書では、ポインターも配列も教えずに、vectorとイテレーターを教えている。しかし、コンテナーのカテゴリーやイテレーターのカテゴリーについては教えていないので、vectorとランダムアクセスイテレーターを前提にした記述になってしまう。

本当はコンテナーのカテゴリーやイテレーターのカテゴリーについて網羅的に教えたいのだが、そうすると具体的なコードがなく抽象的な分類とサポートされる操作といった文章が延々と続くことになってしまう。入門書では直接的なコードがすぐに書けるほうがよいと判断したのでvectorと実質ランダムアクセスイテレーターだけを教えているが、どうにも釈然としない思いがつのる。

プログラミングの入門書の冒頭では、どのようにしてコードを実行するかについて説明するものだ。既存の毎年改訂版が出るような使い捨ての入門書では、この説明のために、例えばVisual Studioのインストール方法の解説からはじめる。しかもご丁寧にいちいちスクリーンショットを載せ、ここのボタンをクリックしてなどといった本当に何のためにあるのかわからない解説が続く。

私が書いている入門書では、そのようなスクリーンショットは一切載せない方針にした。さらに、今年出たばかりの新しいツールに依存してしまうと、数年後に時代遅れになって使えなくなってしまう可能性が高いので、20年前に持っていっても使えるような安定したツールだけを使うことにした。その結果、使うツールはbashとGCCとGNU Makeになった。20年前から変わらないビルドシステムは、おそらく20年後もこのまま使えるはずだが、印刷される書物としてタブ文字と空白文字を区別するように説明するのはつらい。

今書いている入門書はあらゆることが手探りで進められている。例えば変数の宣言方法は以下のとおりだ。

// 整数
auto x = 0 ;
// 浮動小数点数
auto y = 0.0 ;
// 文字列
auto z = "hello"s ;

変数をいきなりこのような方法で教えるC++の入門書は今まで読んだことがないが、思うに最近の言語は強い静的型付けがないか、強い静的な型推論がある言語ばかりで、このような変数の書き方が自然になってきているので、これでよいだろう。

この調子で、最初に教える関数も以下のようになった。


auto plus = []( auto x, auto y ) { return x + y ; } ;

C++では、厳密にはこれは関数ではなくてラムダ式なのだが、こう書くことによって型を意識しないですむ。

ラムダ式を最初に教えることで、関数を渡す関数も自然に教えられるようになった。


int main()
{
    auto for_each = []( auto first, auto last, auto f )
    {
        for ( auto iter = first ; iter != last ; ++iter )
        {
            f( *iter ) ;
        }
    } ;

    std::vector<int> v = {1,2,3,4,5} ;

    for_each( std::begin(v), std::end(v),
        []( auto value ) { std::cout << value ; } ) ;
}

実際、std::for_eachは概ねこのような実装になっているのだと教えている。もちろん、これは本当のstd::for_eachの実装ではないし関数でもないので、厳密には違うが、初心者ならばこの説明でいいだろうと妥協している。

さらに一歩を踏み込んで、vectorの初期化を以下のようにできるのだが、おそらく混乱するだろうからまだやめている。これはC++17で採用されたdeduction guideによるものだ。


// std::vector<int>と同じ
std::vector v = {1,2,3,4,5} ;

今、ようやくアルゴリズムまで進んだのだが、今までに教えたことしか使っていない結果、関数はラムダ式で、コンテナーはvectorしか教えておらず、イテレーターはランダムアクセスイテレーターで、クラスはまだ教えておらず、テンプレートも当然教えていない。lvalueリファレンスだけは無理やり教えたがCV qualifiersは教えていない。

この状態で一体どこまで教えればいいのだろうか。C++を本格的に使うには、当然既存のC++のコードも読む必要があるだろうから、ポインターや配列を理解しなければならず、クラスやテンプレートも学ぶ必要がある。動的メモリ確保も必要だ。しかしこれらの概念を網羅的に解説するのはあまりにも抽象的すぎて、今想定している入門書では難しい。

今書いている入門書は本当に読者に想定していることが少ないので、C++のビルド方法からはじめ、エラーメッセージの読み方も解説したし、gdbの簡単な使い方も解説したい。

それにしても、今はC++を学ぶ対象読者の想定が難しい。一昔前ならばC言語をすでに学び終えた人間を想定すればよかったのだが、今はJavaScriptとかPythonかRubyぐらいしか触ったことのないプログラマーが増えている。彼らはコンパイルしてリンクして実行という仕組みに触れたことがない。

さらに、一昔前ならば想定することができなかった競技プログラマーという人種がいる。彼らは数学力は凄まじいがプログラミング言語には大して執着がなく、必要な計算を最小限のコードで実現できればそれでいいというとても割り切った使い方をする。プログラミング言語の文法をほとんど理解していないのに問題を解くコードは書けるというよくわからない人種だ。

そして入門書は浅く簡略化した解説を続けながらアルゴリズムまで来た。

この後はgdbの使い方、クラス、テンプレート、ポインター、動的メモリ確保、派生クラスあたりの順番で書こうかと思っている。C++の機能の依存関係の解決が辛い。すでに教えている機能だけを使う縛りを入れているので、早く機能を教えないといつまでも簡略化した説明を続けるハメになるが、いきなりポインターを教えても実感が沸かないだろうから、ポインターは相当後になる。

C++17をすでに現場で使っているというキャディ株式会社に話を聞いてきた

$
0
0

CTOが「日本のC++のトップ人材の過半数が所属するイカれた会社にする」という宣言をした会社がある。なんとも壮大な話だ。C++プログラマーの業種は多岐にわたっているので、文字通りに考えると、そのような会社は自動車や旅客機の製造業であり、防衛庁の入札に参加する受注業者であり、OSや独自のプロセッサーを開発するためC++コンパイラー開発者も雇い、さらにはゲームもブラウザーも検索エンジンもクラウドホスティングもと挙げ続ければきりがないほど多方面に展開する大企業である。おそらくすでに名の知れた有名なIT系の大企業をほとんど買収すればそのような状態にはなるのではないかと思うが、金がいくらあっても足りない。

それはともかく、すでに現場でC++17を使っているという。

C++17は2017年に出たばかりの規格で、まだGCCもClangもコア言語はともかくライブラリーまでは完全に実装し終えてない状況だ。そのような状況で今C++17を使えるということは、最新の安定版のGCCやClangを本番環境で使える会社ということだ。果たして何をしているのか。

というわけで、その会社、「キャディ株式会社」に話を聞きに行った。

https://caddi.jp/: 板金加工なら【キャディ株式会社】―即日見積、5日納品、全国配送

Webサイトを見ると、板金加工をする会社だという。これだけではまだC++を使う理由がわからない。

話を聞いてみるとこうだ。

小規模な板金加工の受注生産というのは、小規模ないわゆる町工場が行っている。これまで板金加工をするには、町工場と直接交渉する必要があった。この顧客と町工場の間の交渉には、これまでほとんど技術革新がなかった。キャディはこの顧客と町工場の間に交渉に技術革新をもたらす、いわば仲介業か一次請けのような役割を果たす。

顧客は加工したいモデルデータをキャディのWebサイトからアップロードする。キャディはモデルデータを処理し、加工に必要な費用を見積もって表示する。この見積もりは一瞬で行われる。顧客が発注するとキャディは提携先の町工場に加工を依頼し、完成品を顧客に引き渡す。

顧客の送信したモデルデータから加工費用を一瞬で見積もるために、モデルデータの処理が必要だ。この処理にC++を使っている。

なるほど、C++を使う理由はわかった。ではどうやってこの比較的早い段階にC++17を使うことができるのか。その理由は簡単だった。規模の小さい新興企業だからだ。

現時点で従業員10人超、プログラマーが5人。そのような小規模な開発だからこそ可能になるのだろう。

大企業であればプログラマーとは別に専門のインフラ部署があり、インフラ屋はプログラマーとは少し違う目標を持っている。システムの安定性だ。新しすぎるソフトウェアは問題を引き起こす可能性がある。既存のソフトウェアに問題があるとしても、既知のものであり十分に情報があるので対処可能であるが、新しいソフトウェアの新しい問題は情報も少なく対処も難しい。この結果、インフラ屋はソフトウェアのアップデートに対して保守的になる。特にGNU/Linuxであればとても重要なC++コンパイラーであるGCCにはとても慎重になる。なぜならばGCCは他のほとんどのソフトウェアをコンパイルする重要なソフトウェアなのだから、GCCに問題があればシステムの全てに問題があることになる。

その結果、RHELのようなC++コンパイラーのアップデートが信じられないほどに保守的で時代遅れのディストロが使われる。

プログラマーが数人ですべてをやるような場合、この問題はない。

また、既存のコードが存在しないのも大きいのだろう。既存のコードが存在する場合、新しいコンパイラーによって不具合が修正され、その不具合に依存していたコードが壊れることがあるので、なかなかコンパイラーのバージョンを上げられない問題がある。

C++17をすでに現場で使っている話を聞くと、なんと私が過去に最新のClangを使っていて遭遇した問題に、同じく遭遇していた。

Clangは一時期、glibcのxlocale.hに依存していたことがある。これは非標準のglibcの独自ヘッダーでかなり昔からdeprecated扱いであり、最近削除された。

ディストロのパッケージにある安定版のClangを使いたい場合、私は空のxlocale.hを用意していた。パッケージ管理されたClangのヘッダーファイルを手動で書き換えるよりマシだ。

最新のClangでは修正されている。

Clangはvirtualデストラクターのある基本クラスをvirtual private派生で間接的に持っていた場合、デストラクターのアクセス指定を正しく判断できないregressionがある。Clang 3.3までは正しい挙動だったのだが、3.4から壊れてしまった。

30916 – If a class has indirect private virtual base with non-trivial public destructor, a class cannot access virtual base's destructor.

もう一年以上前にバグは報告してみたが、まだ修正されていないどころか何の反応もない。

こうして考えてみると、最新のC++コンパイラーには不具合も多い。既存の膨大なコードを修正するコストはかなり高い。常に最新のC++コンパイラーを使うのも茨の道だ。しかし、古いコンパイラーを使うということはこれ以上に莫大な既知の規格違反の不具合に対処する不思議なコードを書かなければならなくなるわけで茨の道であることに変わりはない。

ところで、このキャディ株式会社であるが、C++のプログラマーを随時募集しているらしい。応募方法はウェブサイトに記載されているメールアドレスに連絡してほしいとのことだ。

https://caddi.jp/: 板金加工なら【キャディ株式会社】―即日見積、5日納品、全国配送

Viewing all 1280 articles
Browse latest View live