2015-08-27

xkcd 1566と1567

xkcd: Board Game

ボードゲーム

「そして、この山は控除可能カードですね。手札と組み合わせて得点の維持をします」
「そしてこっちは扶養者トークン」

毎年、近所のボードゲームクラブをだまくらかして税金の計算をさせている。

いいアイディアだ。

xkcd: Kitchen Tips

キッチンのコツ

みなさんは、私と同じように、肉が焼けたかどうか判断が着かないことがあるでしょう。

勘に頼るのではなく、サーモメーターを使いましょう。

みなさんは、私と同じように、汚れたお皿とかグラスを投げ捨てていることでしょう。でも、洗えば、再利用できるのです。

スクランブルエッグを作るときは、フライパンを間にはさみましょう。

作るのが簡単になりますし、コンロも汚れません。

みなさんは、私と同じように、冷凍庫に水をぶちまけてからドアを勢い良く占めることで氷を作っていることでしょう。

でも、もっといい方法があるのです。

どうも、馬鹿馬鹿しいテレビ広告手法を皮肉っているらしい。

2015-08-19

江添ボドゲ会@8月の案内

江添ボドゲ会兼引越し祝い@8月 - connpass

引越がようやく落ち着いたので、引越し祝いを兼ねて、自宅でボドゲ会を開催する。

今回は会場にたどり着くところからゲームだ。最寄り駅から1kmほど離れている。

江東区塩浜2-14-2 アライハウスⅡ 101号室

最寄り駅は東西線木場駅。都営バスならば業10か錦13が塩浜二丁目に止まります。

木場駅4b出口から出て南下。イトーヨーカドーを通り過ぎ、中央自動車学校と歩道橋がある塩浜通りで東に進み、サンクスとすき家に挟まれた道を南下し、木場リサイクルの向かい側のマンションの一階の101号室。

入り口のインターホンで101号室を呼び出してください。

2015-08-15

ボルダリング

ボルダリングを始めてからすでに9ヶ月が過ぎた。ボルダリングの技量は徐々に向上している実感がある。

ボルダリングを始めてから、タランチュラとソリューションで壊していたが、今使っているジーニアスは三ヶ月たっても壊れる気配がない。いい靴だ。壊したクライミングシューズは二足とも左足のつま先のソールが剥がれてしまった。足の使い方が悪いからだと指摘されたが、なんとも解せない。

ボルダリングを始めた頃は液体チョークを使っていたが、今は粉チョークに切り替えた。数ヶ月ほどして、ようやくチョークボールを一個使い切った。摩擦力の性能としては、液体チョークのほうが優れているように思う。

今日は久しぶりに錦糸町のT-Wallに行ってきた。一階の水色課題をこなそうとしたが、いくつかできないものもあった。

また、たまたまズボンがやすかったので、今のズボンがだいぶ傷んでいることもあり、購入した。

ロープもしたいものだが、あいにくとなかなかビレイをするパートナーに恵まれないものだ。

ところで、錦糸町のT-Wallのアイシング用の氷を入れてある冷凍庫に、「関節炎、腱鞘炎を抱えながらトレーニングを続ける人を優先してください」と書いてあり、何やら闇を感じた。

2015-08-14

MLからC++テンプレートへのコンパイラー

Evil ML: ML to C++ template language

akabe/evilml

MLからC++テンプレートメタコードへのコンパイラーが公開されている。

以下のMLにおけるクイックソートが、

(* Example: quick sort *)

type 'a list = [] | :: of 'a * 'a list

let rec foldr f xs acc = match xs with
  | [] -> acc
  | x :: xs -> f x (foldr f xs acc)

let length xs = foldr (fun _ acc -> acc + 1) xs 0
let append xs ys = foldr (fun y acc -> y :: acc) xs ys
let filter f xs = foldr (fun x acc -> if f x then x :: acc else acc) xs []

let rec qsort xs = match xs with
  | [] -> []
  | [x] -> [x]
  | pivot :: rest ->
    let ys = qsort (filter (fun x -> x < pivot) rest) in
    let zs = qsort (filter (fun x -> x >= pivot) rest) in
    append ys (pivot :: zs)

let rec nth i xs = match xs with
  | [] -> error
  | x :: xs -> if i = 0 then x else nth (i-1) xs

let l1 = [5; 4; 8; 1; 6; 3; 7; 2]
let l2 = qsort l1
let x0 = nth 0 l2
let x1 = nth 1 l2
let x2 = nth 2 l2
let x3 = nth 3 l2
let x4 = nth 4 l2
let x5 = nth 5 l2
let x6 = nth 6 l2
let x7 = nth 7 l2

(*!
// This is C++ code.

#include <cstdio>

int main () { // We use printf in order to output readable assembly code.
  std::printf("%d  ", x0::val);
  std::printf("%d  ", x1::val);
  std::printf("%d  ", x2::val);
  std::printf("%d  ", x3::val);
  std::printf("%d  ", x4::val);
  std::printf("%d  ", x5::val);
  std::printf("%d  ", x6::val);
  std::printf("%d\n", x7::val);
  return 0;
}
*)

以下のような素敵なC++テンプレートメタコードに変換される。

#include "evilml.hpp"


struct __ml_nil {
  static const int tag = 1000123519;
};

template <class x0, class x1>
struct __ml_cons {
  static const int tag = 478463344;
  typedef x0 fst;
  typedef x1 snd;
};

struct foldr {
  template <class f, class xs, class acc>
  class fun {
  private:
    struct __then2 {
      template <class>
      struct fun {
        static const int tag = 0;
        typedef acc type;
      };
    };
    struct __else2 {
      template <class>
      class fun {
      private:
        struct __then1 {
          template <class>
          class fun {
          private:
            typedef typename xs::fst x;
            typedef typename xs::snd xs1;
          public:
            static const int tag = 0;
            typedef typename
              f::template fun
                <x, typename foldr::template fun<f, xs1, acc>::type>::type type;
          };
        };
        struct __else1 {
          template <class>
          struct fun {
            static const int tag = 0;
            typedef void type;
          };
        };
      public:
        static const int tag = 0;
        typedef typename
          __ml_if<(xs::tag == 478463344), __then1, __else1>::type::
            template fun<void>::type type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename
      __ml_if<(xs::tag == 1000123519), __then2, __else2>::type::template fun
        <void>::type type;
  };
};

struct length {
  template <class xs>
  class fun {
  private:
    struct __fun1 {
      template <class, class acc>
      struct fun {
        static const int tag = 0;
        typedef __ml_int<(acc::val + 1)> type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename
      foldr::template fun<__fun1, xs, __ml_int<0> >::type type;
  };
};

struct append {
  template <class xs, class ys>
  class fun {
  private:
    struct __fun2 {
      template <class y, class acc>
      struct fun {
        static const int tag = 0;
        typedef __ml_cons<y, acc> type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename foldr::template fun<__fun2, xs, ys>::type type;
  };
};

struct filter {
  template <class f, class xs>
  class fun {
  private:
    struct __fun3 {
      template <class x, class acc>
      class fun {
      private:
        struct __then3 {
          template <class>
          struct fun {
            static const int tag = 0;
            typedef __ml_cons<x, acc> type;
          };
        };
        struct __else3 {
          template <class>
          struct fun {
            static const int tag = 0;
            typedef acc type;
          };
        };
      public:
        static const int tag = 0;
        typedef typename
          __ml_if<f::template fun<x>::type::val, __then3, __else3>::type::
            template fun<void>::type type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename foldr::template fun<__fun3, xs, __ml_nil>::type type;
  };
};

struct qsort {
  template <class xs>
  class fun {
  private:
    struct __then8 {
      template <class>
      struct fun {
        static const int tag = 0;
        typedef __ml_nil type;
      };
    };
    struct __else8 {
      template <class>
      class fun {
      private:
        struct __then7 {
          template <class>
          class fun {
          private:
            typedef typename
              xs::fst x;
            struct __then6 {
              template <class>
              struct fun {
                static const int tag = 0;
                typedef __ml_cons<x, __ml_nil> type;
              };
            };
            struct __else6 {
              template <class>
              class fun {
              private:
                struct __then5 {
                  template <class>
                  class fun {
                  private:
                    typedef typename xs::fst pivot;
                    typedef typename
                      xs::snd rest;
                    struct __fun4 {
                      template <class x>
                      struct fun {
                        static const int tag = 0;
                        typedef __ml_bool<__ml_lt<x, pivot>::val> type;
                      };
                    };
                    typedef typename
                      qsort::template fun
                        <typename filter::template fun<__fun4, rest>::type>::
                        type ys;
                    struct __fun5 {
                      template <class x8>
                      struct fun {
                        static const int tag = 0;
                        typedef __ml_bool<__ml_ge<x8, pivot>::val> type;
                      };
                    };
                    typedef typename
                      qsort::template fun
                        <typename filter::template fun<__fun5, rest>::type>::
                        type zs;
                  public:
                    static const int tag = 0;
                    typedef typename
                      append::template fun<ys, __ml_cons<pivot, zs> >::type type;
                  };
                };
                struct __else5 {
                  template <class>
                  struct fun {
                    static const int tag = 0;
                    typedef void type;
                  };
                };
              public:
                static const int tag = 0;
                typedef typename
                  __ml_if<(xs::tag == 478463344), __then5, __else5>::type::
                    template fun<void>::type type;
              };
            };
          public:
            static const int tag = 0;
            typedef typename
              __ml_if<(xs::snd::tag == 1000123519), __then6, __else6>::type::
                template fun<void>::type type;
          };
        };
        struct __else7 {
          template <class>
          class fun {
          private:
            struct __then4 {
              template <class>
              class fun {
              private:
                typedef typename xs::fst pivot;
                typedef typename
                  xs::snd rest;
                struct __fun6 {
                  template <class x9>
                  struct fun {
                    static const int tag = 0;
                    typedef __ml_bool<__ml_lt<x9, pivot>::val> type;
                  };
                };
                typedef typename
                  qsort::template fun
                    <typename filter::template fun<__fun6, rest>::type>::type ys;
                struct __fun7 {
                  template <class x10>
                  struct fun {
                    static const int tag = 0;
                    typedef __ml_bool<__ml_ge<x10, pivot>::val> type;
                  };
                };
                typedef typename
                  qsort::template fun
                    <typename filter::template fun<__fun7, rest>::type>::type zs;
              public:
                static const int tag = 0;
                typedef typename
                  append::template fun<ys, __ml_cons<pivot, zs> >::type type;
              };
            };
            struct __else4 {
              template <class>
              struct fun {
                static const int tag = 0;
                typedef void type;
              };
            };
          public:
            static const int tag = 0;
            typedef typename
              __ml_if<(xs::tag == 478463344), __then4, __else4>::type::
                template fun<void>::type type;
          };
        };
      public:
        static const int tag = 0;
        typedef typename
          __ml_if<(xs::tag == 478463344), __then7, __else7>::type::
            template fun<void>::type type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename
      __ml_if<(xs::tag == 1000123519), __then8, __else8>::type::template fun
        <void>::type type;
  };
};

struct nth {
  template <class i, class xs>
  class fun {
  private:
    struct __then11 {
      template <class>
      struct fun {
        static const int tag = 0;
        typedef void type;
      };
    };
    struct __else11 {
      template <class>
      class fun {
      private:
        struct __then10 {
          template <class>
          class fun {
          private:
            typedef typename xs::fst x;
            typedef typename
              xs::snd xs1;
            struct __then9 {
              template <class>
              struct fun {
                static const int tag = 0;
                typedef x type;
              };
            };
            struct __else9 {
              template <class>
              struct fun {
                static const int tag = 0;
                typedef typename
                  nth::template fun<__ml_int<(i::val - 1)>, xs1>::type type;
              };
            };
          public:
            static const int tag = 0;
            typedef typename
              __ml_if<(i::val == 0), __then9, __else9>::type::template fun
                <void>::type type;
          };
        };
        struct __else10 {
          template <class>
          struct fun {
            static const int tag = 0;
            typedef void type;
          };
        };
      public:
        static const int tag = 0;
        typedef typename
          __ml_if<(xs::tag == 478463344), __then10, __else10>::type::
            template fun<void>::type type;
      };
    };
  public:
    static const int tag = 0;
    typedef typename
      __ml_if<(xs::tag == 1000123519), __then11, __else11>::type::
        template fun<void>::type type;
  };
};

typedef __ml_cons
  <__ml_int<5>, __ml_cons
     <__ml_int<4>, __ml_cons
        <__ml_int<8>, __ml_cons
           <__ml_int<1>, __ml_cons
              <__ml_int<6>, __ml_cons
                 <__ml_int<3>, __ml_cons
                    <__ml_int<7>, __ml_cons<__ml_int<2>, __ml_nil> > > > > > > > l1;

typedef qsort::fun<l1>::type l2;

typedef nth::fun<__ml_int<0>, l2>::type x0;

typedef nth::fun<__ml_int<1>, l2>::type x1;

typedef nth::fun<__ml_int<2>, l2>::type x2;

typedef nth::fun<__ml_int<3>, l2>::type x3;

typedef nth::fun<__ml_int<4>, l2>::type x4;

typedef nth::fun<__ml_int<5>, l2>::type x5;

typedef nth::fun<__ml_int<6>, l2>::type x6;

typedef nth::fun<__ml_int<7>, l2>::
  type x7;

// This is C++ code.

#include <cstdio>

int main () { // We use printf in order to output readable assembly code.
  std::printf("%d  ", x0::val);
  std::printf("%d  ", x1::val);
  std::printf("%d  ", x2::val);
  std::printf("%d  ", x3::val);
  std::printf("%d  ", x4::val);
  std::printf("%d  ", x5::val);
  std::printf("%d  ", x6::val);
  std::printf("%d\n", x7::val);
  return 0;
}

ドワンゴ広告

この記事はドワンゴ勤務中に見つけたのでメモ代わりに書いた。

ドワンゴ社内に関数型プログラマーが何人いるかは把握していない。

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

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

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

2015-08-13

Emscriptenがpthreadを実験的にサポート

Emscripten gains experimental pthreads support! - Google Groups

Emscrptenがpthreadを実験的にサポートしたそうだ。

JavaScript上でスレッドを実装する上で障害になるのは、スレッドに相当する方法が存在しないということだ。Web Workerは実行媒体ごとに隔離されて、メッセージパッシングで他の実行媒体と通信をする仕組みになっている。これは同じメモリに複数の実行媒体からアクセスするというスレッドとは異なり、プロセスに近い。

現在、JavaScript上で共有メモリを扱えるようにしようというドラフト規格、SharedArrayBufferが議論中であり、Firefox Nightlyが実験的実装を進めている。この機能を用いて、Emscriptenでpthreadを実験的に実装したそうだ。

ドワンゴ広告

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

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

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

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

2015-08-12

Lenovoのファームウェアがファイルシステムを改ざんするクソ仕様なので絶対に使ってはいけない

最近のLenovoのBIOSのアップデートに以下のものがある。

Lenovo Newsroom | Lenovo Statement on Lenovo Service Engine (LSE) BIOS

この脆弱性はLenovoの一部の顧客用PCにインストールされているBIOS中に存在するMicrosoft Windows機構に関与する機能、Lenovo Service Engine(LSE)に関連したものである。

などと抽象的でわけのわからない文面で脆弱性の説明と修正した旨が案内されている。では具体的にどんな脆弱性だったのか。驚くべきバカなことが行われていた。

Lenovo G50-80 dialog box - Ars Technica OpenForum

Windows 7か8をブートする前に、BIOSはC:\Windows\system32\autochk.exeがLenovoのものかMicrosoftオリジナルのものかどうかを調べ、Lenovoのものでなければ、オリジナルはC:\Windows\system32\0409\zz_sec\autobin.exeに移動され、独自のautochk.exeが書き込まれる。

ブート中に、Lenovoのautochk.exeは、LenovoUpdate.exeとLenovoCheck.exeをsystem32ディレクトリに書き込み、インターネット接続が行われた場合に、どちらかをサービスとして実行する。これが何をしているのかについて詳しくは知らないが、この内の一つは、http://download.lenovo.com/ideapad/windows/lsebios/win8_en-us_32_oko.jsonを読み込むらしい。これはsslを使っていないし、"ForceUpdate"というパラメーターがあることから、どうも怖い。通信を改変できる誰からでも(public wifiとか)任意のコードを実行可能な脆弱性として利用できそうだ。

アホか? Lenovoは脳の髄までアホなのか? なぜBIOSがファイルシステムの、しかもOSの重要なファイルを改変しているのだ? Windowsのアップデートやアップグレードで動かなくなることは必然として、悪意すら感ずるほどのスガスガしいマヌケっぷりだ。

Lenovoがこれを実装するのに必要な技術者の誰か一人でも、「俺の屍を越えて行け」という態度を取らなかったのは驚くべきマヌケっぷりだ。Lenovoは上から下までマヌケしかいないか。

Lenovo製品を使うのは大いにセキュリティ上のリスクだ。絶対に使ってはいけない。

Lenovo quietly installed software on laptops, even if you wiped it

なお、Lenovoが利用していたのはMicrosoft公認(Lenovoの脆弱性が発覚してから利用規約が修正された)の機能で、もともとは盗難防止プログラムなどの、Windowsの再インストールを経ても維持されるソフトウェアをPCベンダーが作りたいときに使えるWindows Platform Binary Tableという機能だったらしい。

2015-08-09

引越しの片付けがようやく終わりそうだ

先月引越しをしたのだが、色々と日常の雑事に追われていて、部屋の片付けがなかなかできなかった。この週末は一念発起して残りのダンボールの山を片付けた。ようやくリビングが空いたので、これでボドゲ会が開けるようになった。

最後まで片付かなかった荷物は紙の本だ。しかたなく本棚を買った。

また、今回、事務用の折り畳み机と折りたたみ椅子を買ってみた。人が来た時に使え、普段は邪魔にならない家具が欲しかったので、あまりご家庭にあるものではないが、思い切って買ってみた。使ってみるとこれがなかなか具合がよい。値段が安いのもいい。ちょっとしたおしゃれな机と椅子は何万もする。事務用の折りたたみ椅子と机は安い上にはるかに機能的だ。

さて、家の中が片付いたので、近々ボドゲ会や引越し祝いのパーティを開きたいものだ。

2015-08-07

GCCのconceptブランチがtrunkにマージされる

Jason Merrill - Huge C++ PATCH to merge c++-concepts branch

GCCのconceptブランチがtrunkにマージされるようだ。

現在、Concept TSとして提案中のコンセプトは、C++11に提案されていたコンセプトとは違い軽量版で、コンセプトチェック機能のみを提供している。

ドワンゴ広告

今年の8月14日は、とある理由により有給を取得するドワンゴ社員が多そうだ。

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

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

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

2015-08-04

C++参考書、C++11/14 コア言語を9月に出版予定

C++11/14のコア言語の参考書。「C++11/14コア言語」が出版社ドワンゴ、販売KADOKAWAとして、9月に出版される。内容は、以下を書籍にしたものだ。内容としてはすでにすべて読むことができる。

EzoeRyou/cpp-book

EzoeRyou/cpp14-appendix

アマゾンには情報が掲載されたようだ。

Amazon.co.jp: C++11/14 コア言語: 江添 亮: 本

紙の本の他にも、KindleとepubとPDF版も現時点で出す予定だ。また、もちろん本のソースコードも公開される。

ソースコードは、Markdown形式だ。もともとこの本はXHTMLで手書きされたが、それでは扱いづらいため、これを一度Markdownに変換した上で修正し、pandoc経由でtexに変換してから各フォーマットを生成している。不自由なフォント以外のソースコードは公開できるだろう。

本の帯に書く短い説明として、「他の解説書ではわからないC++コア言語の詳細を不必要なまでに解説」などと冗談で言ったら、本当に採用されてしまった。本の内容は、通常C++を書くのであれば、まず書かないだろうコードが合法かどうかや、その意味まで解説している。規格としては、コードは合法か違法かを規定しなければならず、また合法の場合は、その挙動も規定しなければならないからだ。

例えば、クラスやenumは名前は、変数やデータメンバーの名前によって隠されるという規程がある。

class ClassName {} ;

void f()
{
    ClassName ClassName ; // OK、ClassName型の変数、ClassName

    ClassName x ; // エラー、ClassNameは、ここでは変数名を指す。

    class ClassName x ; // OK、明示的にクラス名であると指定している。
}

クラス名を変数名で隠すこのようなコードは、現実ではお作法的に推奨できないが、規格上は合法である。

この参考書は、このような些細な、現実的な実務で使うコードには推奨できないような例も多い。規格上は興味深いが、それを知っても日々のコーディング力にはあまり貢献しないような些細な詳細が書かれている。

ドワンゴ広告

出版社はKADOKAWAとなっているが、販売がkADOKAWAで、出版はドワンゴが行う。組版などの作業はドワンゴ社内で行われた。編集者は私の席のとなりに座っていたため、極めてやりやすい。しかし、出版社が私の雇用主で、編集者が同僚というのはなかなかない環境ではなかろうか。

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

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

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

2015-08-02

佐川急便のWeb上の再配達受付がクソすぎる件

アマゾンで家具を注文したのだが、土曜日の不在中に届けに来たようで、不在届が入っていた。そこで。再配達で明日の時間を指定して受け取れるようにしようと試みた。その結果、佐川急便のWeb上の再配達申し込みは、この2015年にありえないほどクソであることが明らかになった。

私は電話は持っていないし、10桁以上もある受付番号やら何やらを電話越しに番号でブッシュするのも面倒なので、Webサイト上で申し込むようにした。

ところが、このWebサイト上での申し込みが、非常にクソだったのだ(2015-08-02現在)

まず、電話による従来の再配達の手順を書いてみる。

  1. 受付用の電話番号に電話する
  2. 自分の電話番号をプッシュ信号で通知する
  3. 受付番号をプッシュ信号で通知する
  4. 再配達希望日時をプッシュ信号で通知する

プッシュ信号経由で合計25個ほど数字を通知する必要がある。これはだるいが、技術上の制約上いかしかたないことだ。

ではWeb上で再配達を申し込む場合、どうなるのか。

まず、ユーザー登録をしなければならない。メールアドレスを入力し、やってきたメールに示されたURLにアクセスして、利用規約に同意し、ユーザーIDとパスワードと苗字と名前とそのカナ表記と生年月日と性別と郵便番号と住所とその他諸々の入力をしなければならない。受付番号を入力して再配達を申し込むのは、このユーザー登録をしてからだ。

利用規約はある程度長いが、第三者と個人情報を共有するような罠条項は一見したところないようだ。

さて、あまりにも入力すべき個人情報が多すぎる。名前はまだわかるが、なぜ生年月日や性別や住所まで入力しなければならないのか。電話による従来の再配達に比べて、入力すべき項目があまりにも多すぎる。生年月日や性別といった個人情報を収集する意図がわからないし、電話による再配達受付では住所など入力する必要がない。

さて、この住所がクセモノだ。なぜか正しく入力したのにバリデーションがはねられる。一体なぜだろうか。住所を正しく入力せよ以外のメッセージはない。私は正しくUTF-8としてデコードできるバイト列使っているはずだし、クロスサイトスクリプティングやSQLインジェクションを引き起こすような文字列を入力してもいない。ここで詰まってしまった。なぜ入力が受け付けられないのか。

しかし、ふとみると、入力欄には注意書きとして、(全角20文字以内)という文字列があるではないか・・・まさか。

筆者はASCIIに含まれる文字をすべて似たような意味のUnicodeで置き換えてみた(1を1にするような変換)。すると住所のバリデーションが通った。

アホか? アホなのか?

そして、次には、メール通知のチェックボックス。メール通知など要らないので、全て外そうとすると、どれかひとつはメール通知を受け取るにしなければならないというバリデーションエラーが。

この時点で、筆者は登録を辞めた。佐川急便のWeb上の再配達受付の設計、実装は100万人月で行われたとしか思われない。信じられないクソさだ。

最近、アマゾンは佐川急便を使うようになったそうだが、だいぶ不便だ。もうアマゾンを使うのが面倒になった。

2015-07-29

GitHub運営により言葉狩りが行われている

WebMConverterというffmpegのAviSynthのGUIフロントエンドのGitHubレポジトリで、GitHub運営により規約違反の暴力的な言葉が使われたとして削除の警告を受けたことによる変更があった。

https://imgur.com/QC51FZz · nixxquality/WebMConverter@c1ac0ba

https://imgur.com/QC51FZz

文脈は、「バカでも使える」という意味で使っている。

変更では、for Retards(池沼どもでも使える)をfor Gits(クソ野郎どもでも使える)に変えている。

しかし、githubはgit(クソ野郎)という暴力的な言葉を含むのだが、それはいいのだろうか。

2015-07-22

C++標準化委員会の文書 2015-05 post-Lenexaのレビュー: M4531-N4544

N4531: std::rand replacement, revision 3

めでたくdeprecatedされたrandの代わりになるお手軽に使える乱数ライブラリ、randintの提案。

randintは関数テンプレートとなっていて、整数型に対して特殊化できる。

// -10から10までの間のint型の乱数を生成
auto a = std::randint( -10, 10 ) ;
// 0Lから10Lまでの間のlong型の乱数を生成
auto b = std::randint( 0L, 10L ) ;

randintの乱数を生成するために、スレッドごとにdefault_random_engine型のオブジェクトが予測不可能な状態に初期化される。つまり、プログラムの実行ごとにrandintの結果は変わる。

乱数エンジンの状態を再び予測不可能な状態にするには、std::reseed()を呼び出す。

reseedに値を指定すると、状態を予測可能にできる。これは、デバッグ目的に使える。

その他に、乱数生成を関数オブジェクトとして引数に取らない版のshuffle, sampleアルゴリズムが追加される。

N4532: Proposed wording for default comparisons

クラスにデフォルトの比較演算子を生成する提案の文面案。

クラスにvirtual基本クラス、virtualメンバー関数、mutableメンバー、ポインター型の非staticデータメンバー、ユーザー提供されたコピー/ムーブコンストラクターと代入演算子はデフォルトの比較演算子は生成されない。

N4533: Make exception-specifications be part of the type system, version 3

例外指定を型の一部に含める提案。

N4534: Data-Invariant Functions (revision 3)

サイドチャネル攻撃を防ぐためのライブラリ。

value<T>の形で利用して、値の比較ができる。値によって外部から観測可能な物理的挙動(実行時間やメモリアクセスパターンなど)が異なる場合、SONO物理的挙動を外部から観測することで、値が推測できてしまう。valueライブラリは、物理的挙動の差をなくしてくれる。

今回の提案では、barrierが入っていたり、イテレーターの範囲の値がそれぞれ等しいか比較するequal、条件でどちらかのイテレーターの範囲をコピーするcopy_conditional、イテレーターを進めるlookupが入っている。

N4535: Feature-testing preprocessor predicates for C++17

機能テスト推奨で提案されていた__has_includeと__has_cpp_attributeをC++17に追加する提案。

N4536: clamp: An algorithm to 'clamp' a value between a pair of boundary values (Draft) -

clamp( value, min, max )の提案。

#include <functinal>

int main()
{
    auto a = std::clamp( 5, 1, 10 ) ; // 5
    auto b = std::clamp( 11, 1, 10 ) ; // 10
    auto c = std::clamp( -1, 1, 10 ) ; // 1
}

ある値をある範囲に収めることはプログラミングではよくある処理である。標準にその方法がない場合、非統一的な方法で書かれてしまう。例えば以下のように。


auto clamped_value = std::min( std::max( value, min_value ), max_value );

また、範囲版も提案されている。


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

// { 3, 3, 3, 4, 5, 5, 5, 5, 5 } 
std::clamp_range( v.begin(), v.end(), v.begin(), 3, 5 ) ;

ちなみに、ドワンゴ社内ではclamp( min, value, max )という引数の並びを好む人もいるようだ。また、clampを関数オブジェクトを返す関数にして、clamp(min, max)(value)などという文法を好む人もいるようだ。

N4537: Adding Symmetry Between shared_ptr and weak_ptr

weak_ptrに欠けているshared_ptrの機能を追加する提案。

shared_ptr<vector<int>>のような型から、vectorのある要素へのポインターを返すweak_ptrがほしいとする。shared_ptrにはそのための機能がある。所有権を管理するポインターと、getで変えるポインターをコンストラクターの引数で別々に指定することができるのだ。

shared_ptr<int> first_elt_strong(const shared_ptr<vector<int>>& vec)
{
    return shared_ptr<int>(vec, &vec->at(0));
}

さて、戻り値に返すポインターに、それほど強い参照が欲しくない場合、戻り値の型をweak_ptrに変えることが考えられる。すると、以下のようになる。

weak_ptr<int> first_elt_strong(const shared_ptr<vector<int>>& vec)
{
    return shared_ptr<int>(vec, &vec->at(0));
}

これは動く。ただし、必要以上に非効率的である。まず、shared_ptrを作るので参照カウンターがインクリメントされる。次に、weak_ptrが作られるので、weak参照カウンターがインクリメントされる。そして、shared_ptrが破棄されるので、参照カウンターがデクリメントされる。

実に3回もの不可避なメモリアクセスが発生しているではないか。技術的には、メモリアクセスはweak参照カウンターの一回だけにできるはずである。しかし、weak_ptrのコンストラクターにはshared_ptrのコンストラクターがない。そのため、shared_ptrを経由しなければweak_ptrが作れない。

この問題を解決するために、提案ではweak_ptrにも同等のコンストラクターを追加している。

weak_ptr<int> first_elt_strong(const shared_ptr<vector<int>>& vec)
{
    return weak_ptr<int>(vec, &vec->at(0));
}

もうひとつの問題は、shared_ptrからweak_ptrを作り出すには、キャストが必要だということだ。以下の例を考えてみる。

template < ObjectType >
void f( ObjectType & obj )
{
    auto sp = obj.get_shared_ptr() ;
    auto wp = weak_ptr<ObjectType>(sp) ;
    // ...
}

このコードは、あまりジェネリックではない。もし、obj.get_shared_ptr()の返すshared_ptrが、shared_ptr<ObjectType>ではなく、shared_ptr<BaseClassOfObjectType>であるかもしれない。あるいは、std::shared_ptrではなく、独自のcustom_shared_ptrを返すかもしれない。

そもそも、このコードでは明示的に型を指定している部分は、弱体化(weakening)している部分だけである。weakeningに明示的で具体的な型を必要とするのはおかしい。

そのため、論文ではshared_ptrにweak_ptrを返すunlockメンバー関数の導入を提案している。

template < ObjectType >
void f( ObjectType & obj )
{
    auto sp = obj.get_shared_ptr() ;
    auto wp = sp.unlock() ;
    // ...
}

weak_ptrからshared_ptrを作り出す既存のメンバーとしてlockがあるので、その逆としてunlockだ。

[PDF注意] N3538: Technical Specification for C++ Extensions for Concurrency

Concurrency TS。非同期処理のための様々なライブラリの改良と追加。

N4539: C++ Standard Evolution Active Issues List
N4540: C++ Standard Evolution Completed Issues List
N4541: C++ Standard Evolution Closed Issues List

C++の新機能提案に対する既知の問題集

[PDF注意] N4542: Variant: a type-safe union (v4).

型安全unionライブラリ、variantの提案。boostのものとはvariantのネストを認めないなどで違っている。

[PDF注意] N4543: A polymorphic wrapper for all Callable objects

std::functionのコピー不可能版のstd::unique_functionの提案。

std::functionは関数オブジェクトがコピー可能であることを要求する。コピー可能ではない型は格納できない。std::unique_ptrはコピー不可能な型を格納できる。

コピー不可能であること以外は、std::functionと同等のインターフェースを持っている。std::functionでstd::unique_functionを初期化することはできる。逆はできない。

N4544: October 2015 WG21 Meeting (Kona)

2015年10月にハワイで行われる会議の案内。

ドワンゴ広告

先週の土曜日に、ドワンゴのセミナールームでTopCoderの競技プログラミングの予選、TCO15 in Tokyoが開催された。

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

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

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

2015-07-18

引越しと信用

先日、引越しを終わらせた。今回の引越しで、思うところが色々とあるので、書いてみる。

まず、今回の引越しでは、自分でシェアハウスを作ろうと試みた。そのために、色々とシェアハウス向きの物件を借りようとしたのだが、これが借りられない。理由は信用だ。

何軒かの不動産屋を回ってみて感じたこととしては、渡のつくりたいシェアハウスと、不動産屋が一般に考える不動産屋に、かなりの隔たりがあるということだ。

私の作りたいシェアハウスというのは、住人がそれぞれ一人暮らしするぐらいの賃料を払って、キッチンや風呂やリビングなどの共用部分の設備が豪華な賃貸物件に複数人で住むというものだ。

ところが、どうも不動産屋の想定するシェアハウスとは、クッソ古くてボロボロな2LDKぐらいの部屋に出稼ぎ外国人を含む10人以上が住むものらしい。

紹介される物件というものも、その賃料と地区年数なら、住人候補は全員、もっとマシな場所に一人で住むというようなものばかり。完全に認識の隔たりがあるようだ。

そして、肝心の賃貸物件が借りられない。どうやら、ある程度の規模(4LDKとか月家賃が20万円とか)の賃貸物件は、東京では個人に貸してくれないようなのだ。法人契約を求められる。しかし、私が借りようとしている物件は、事務所や社宅には不都合な間取りなのだが。

さて、仕方がないので、婚約者と二人暮らしでもしようかと思い、お互いの職場近くに2LDK程度の賃貸物件を借りようと試みた。

いくつか中を見た結果、結局、相場より高い物件はあれど、相場より安い物件というものは存在しないものだと結論した。相場より安そうにみえる物件には何らかの理由がある。

色々考えた結果、建物と部屋の維持管理に十分な金を投じている賃貸物件を借りた。多少高かったが、ちゃんと壁紙が張り替えられており、クーラーが比較的新しく、洗面台やトイレなども新しい物件だ。さらに、ベランダが温室のようにガラス張りになっていて、雨に濡れない。所有者によると防犯を考えてとのことらしいが、ガラスは簡単に割れるので、その点では疑問だ。

この賃貸物件の不満な点は、周辺に住宅と工場とオフィスビルしかなく、やや不便であるということだ。とは言え、コンビニは近いし、イトーヨーカドーも近くにあるので、とりあえず日常の買い物は問題なさそうだ。

さて、物件を借りる際には、保証会社が必須であるという。筆者は元一部上場企業(カドカワとドワンゴが合併して、持株会社カドカワドワンゴの子会社という形になったので、ドワンゴは上場廃止となったのだ。)に雇用されていて定期的な給与所得があり、貯金があり、借金もない。私は金銭的に十分に信頼できる人間である。ところが、思わぬ問題に出くわした。保証会社の審査を進めるには、携帯電話番号が必須であるという。

筆者は携帯電話を所有していない。その理由は、筆者が契約書を読む人間だからだ。およそ、携帯電話の契約書をまともに読めば、携帯電話は契約してはならないということがわかる。携帯電話を契約する人間は契約書をまともに読んでいないに違いない。そんな人間は果たして信用に値するのだろうか。

ところが、不思議なことに、この現代日本社会では、携帯電話の所有は信用に値するらしい。

これは由々しき問題だ。賃貸契約を結ぶには、金の他に、信用が必要だ。そして、この日本国では、信用は住所と携帯電話で担保されている。住所も携帯電話も持っていないものは、信用がないため賃貸契約を結べない。しかし、住所と携帯電話を同時に消失した場合、どうやって復帰するというのだろうか。

どう考えても、住所と携帯電話を同時に消失した場合、金では復帰できないように思われる。金さえあれば土地と家を買えるのではないかと思うかもしれない。しかし、携帯電話と住所がない状態で、不動産登記をどうやって行うのか。

筆者の考えた復帰方法では、どうしても他人の信用に乗るしかない。すなわち、誰か支援者を得て、支援者の住所に住民票を移す。これで住所ができるので、携帯電話を契約する。そして賃貸契約を行う。

筆者はできるだけ物を持たない生活をしている。その上で、携帯電話は不必要であるのみならず、その契約内容は危険であり、かつ、私の日々の活動を妨げる妨害装置でもある。携帯電話は一切信用できないものであり、携帯電話を所有することで信頼が生じるのは全く理解できない。

携帯電話は連絡手段であるという者がいる。しかし、この2015年には携帯電話は最適な連絡手段ではない。

仕方がないので、私のかわりに、私の婚約者が賃貸契約をすることになった。ここで保証会社の謎の要求が出てくる。なんと、先に審査すら拒否した私を、連帯保証人にすれば審査を通すというのだ。審査すら拒否するほどの信用のない私を連帯保証人にして得られる信用とはなんだろうか。おぼつかないものだ。私の連帯保証人にするならば、婚約者の親を連帯保証人から外してほしいものだ。

さて、とにかく家は確保した。引越しにはやたらとカネがかかった。私は普段から金を使う当てがないので、貯金のみ無駄に溜まっていて、支払いに問題はないのだが、この額は引越し難民がでるのも理解できる額だ。

ところで、自宅にはまだインターネット回線を引いていない。せっかくだからISPにもこだわろうかと、IIJmioひかりを契約しようと思ったのだが、なんとクレジットカード払いのみ。さて・・・これはクレジットカードを作らねばならぬのか。この分では、ネット回線を引くのは時間がかかりそうだ

そして、色々と入用なものがある。特にキッチン用品を揃えなければならない。さしあたって、レンジを買わなければならない。安いものを買うか、高いものを買うか思案している。大きな鍋も必要だ。

元Google社員、社内での給与額の公開運動について語る

Ex-Googler says she exposed company-wide pay inequality with crowdsourced spreadsheet | Fusion

EricaJoy on Twitter: "a thing bothered me yesterday and it's still bothering me today and so now i want to tell a story."

元Google社員で今はSlack社員の黒人の女であるErica Bakerが、Googleが公民権運動で有名なIda B. Wellsを取り上げたことをきっかけに、Google社内に蔓延する差別について語っている。

昔不満であることは、今もってなお不満である。そこで、ひとつ話をしようと思う。

ある日曜日、元同僚の何人かと私は退屈で、給料について社内SNSで話していた。そして、あるスプレッドシートが作られた。

我々はスプレッドシートに給料額を書き込んで、社内SNSに私のアカウントへのリンクとともに貼った。山火事のように広がっていった。

社内のいたるところで共有された。誰かがグラフを付け足して給与額の少なさを炙りだした。

私はスプレッドシートの管理をしていた(性別欄の表記統一とか、為替とか、そのへん)

さらに共有は続く。さらに人が給与額を付け足していく。物事が大きくなってきた。

私は、月曜日か火曜日に、上司に呼ばれた。上層部が不満であるという。上司は不満であるという。なぜ私はそんなことをしたのだ?

「これから何が起こるかわかっているのかね?」
何も。給料額を公開した被雇用者を不当に扱うのは違法である。
「うーむ・・・
・・・ ・・・」

ミーティングは終わった。スプレッドシートはさらに大きくなっていく。同僚は私に感謝し始めた。同僚は私に対してピアボーナス(Peer Bonus)を送り始めた。

ピアボーナスとはなにか。もし、なにかいいことをした場合、同僚はその社員にピアボーナスを付加する。ポアボーナスが付加された社員は、次の給料が150ドル上乗せされる。

この時私が学んだ重要なこととして、ピアボーナスは上司の採決が行われるということだ。私の上司は私に対するすべてのピアボーナスを却下した。

これが会社にとっていいことなのかどうかわからない。その結果が気になるところだ。ピアボーナスが一度却下されると、取り消すことはできないのだ。

ところで、これに関与していた別の同僚、白人の男(良き友人でありここで名前を挙げることはしない。彼にその気があれば自ら名乗りでるであろう)もまた、ピアボーナスを受け取っていた。

白人の男のピアボーナスは却下されなかった。私は自分が却下されたことを告げた。彼は憤った。このことをみんなに言いふらそうとした。私は差し止めた。

一部の社員がこのことを知った。元の会社の裏チャンネル(IRCで#yallknowwhoyouareだったw)で広まった。

ピアボーナスを却下するというのは聞いたことがない。そういうことが可能であることも社員は知らなかった。それが知られた時、反抗が起こった。私の言っていないことだ。

ところで、スプレッドシートはまだ続いて、広がっていった。給与帯を公開することについて人事に質問が投げられた(wwww ダメ)

大半の社員は、これがいいことであると考えた。ピアボーナスが入り続け、却下され続けた。

ピアボーナスのひとつが承認された。ほとんど却下されたあとに。なぜならば、ピアボーナスを送った社員は、その理由について極めて曖昧に書いたがために。

スプレッドシートについて言及するピアボーナスはすべて却下された。最終的に7個ぐらいあっただろうか。

上層部はいまだに不満であった。何人かの、これまで私が技術的顧問として支持してきた者達は、私に話しかけなくなった。¯\_(ツ)_/¯

私が会社を辞める前に、約5%ほどの元同僚が、スプレッドシートで給料額を共有していた。社員はスプレッドシートのデータに従って公平な給与を求め、そして得た。

天地が崩墜することはない。給与額が公開されたからと言って炎上することなどない。ただ、一部の人間の待遇が上がるだけだ。

私は会社を辞める前に、人事によってスプレッドシートが消されないように、スプレッドシートの所有権を誰かに渡した(起こり得たことだ)

私がこのことについて考えているのは、Googleが昨日、Ida B.をdoodleに載せたことについて皆が賞賛しているからだ。

Ida B. Wellsは素晴らしい。彼女はあそこまでの規模の変化をもたらした。もし、私が彼女の半分にも値するほどの女であれば、私は相当のことができる。

私はIda B. Wellsには遠く及ばないものの、たまに、人間の善のために、既存の慣習を打ち壊すことをする。

私は正義と公平を信じており、必要とあればこの2つを守るために戦う。

正義と公平のための、Google社内での戦いは、あまりうまくいかなかった。給与額の共有は一例に過ぎない。Bloggerポルノ、本名、その他多くのことがある。

もし、差別主義者(有名な差別主義者)に、帰れと言えば、クソ面白いことが起こる。差別主義者が自己保身をするためだ。明らかに。

さて、さあさあ。GoogleはIda B. Wells doodleをした。

もし、Ida Wellsがまだ生きていて、Googleで働いていたとしたら、非公開ミーティングが多数設定されて、「彼女のキャリアパス」について話されていることは保証できる。

ということだ。doodleで共有するということは、正義や公民差別についての支援をしているとはかぎらないということだ。

ドワンゴ広告

最近、アメリカでは給与額の公開という話題が熱い。同じ能力で成果を出しているのであれば同じ給与であるべきという公平感といい、人種、性別によって給料を差別しているのではないかといい、給料額を公開しない慣習自体に疑問が投げかけられている。

ドワンゴも給料額の公開に関しては同じ山の石だ。。

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

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

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

2015-07-14

C++標準化委員会の文書 2015-05 post-Lenexaのレビュー: N4521-N4530

Merge Fundamentals V1 into V2

Library Fundamentals TSのV1とV2をマージする提案。

V1とV2が分かれていた理由は、NB投票をする際の混乱を防ぐためだったそうだ。

余計に分かりづらかった気がするのだが。

N4522: std::atomic_object_fence(mo, T&&...)

atomic_object_fenceの提案。atomic_thread_fenceと似ているが、これはVariadic Templatesで任意個のリファレンスを取る。リファレンスに取ったオブジェクト以外の順序は未規定である。

N4523: constexpr std::thread::hardware_{true,false}_sharing_size

C++にキャッシュラインサイズを取得するライブラリの追加。

C++11では、std::thread::hardware_concurrency()が追加された。これは、独立して実行できるスレッドの数を返す(例えばコア数)。これは実装の際のヒントに使える。

同じ考え方で、キャッシュラインサイズをヒントとして取得したい。標準ライブラリに入れることで、移植性の高い方法でキャッシュラインサイズが取得できる。しかし、キャッシュラインそのものの定義が実装ごとに異なり移植性がない。

そのためこの提案では、目的を絞った二種類のキャッシュラインサイズ情報を取得できるようにしている。false-sharing sizeとtrue-sharing sizeだ。

false-sharingとは、2つの独立したオブジェクトが同じキャッシュライン上に乗っているがために、一方のオブジェクトに変更が加えられると、もう片方も同期のためにストールすることをいう。false-sharing sizeとは、2つのオブジェクトがfalse-sharingを避けるために取るべきオフセット値を返す。

true-sharingとは、2つのオブジェクトを合わせたメモリーフットプリントとアラインメントが同じキャッシュラインに乗るサイズを返す。

これらの値は、alignas()の中で使うのに最適である。

namespace std {
  class thread {
    // ...
  public:
    static constexpr size_t hardware_false_sharing_size = /* implementation-defined */;
    static constexpr size_t hardware_true_sharing_size = /* implementation-defined */;
    // ...
  };
}

著者はGoogle社員とnVidia社員になっている。nVidia社員が著者になるのはなかなか珍しい気がする。

N4524: Respect vector::reserve(request) Relative to Reallocation

std::vector::reserveは指定したサイズ以上のストレージを確保することが規格で規定されている。この提案は、reserveは指定したサイズを確保するように文面を変更する提案である。

初心者が期待している挙動として、サイズを指定したら、それ以上にストレージを浪費してほしくないということがまずある。また、既存のlibstdc++, libc++, MSVC2013は、指定されたサイズをそのままあロケーターに渡す実装をしている。そのため、これは単に既存の挙動を標準化するだけである。

この提案は、vector<bool>には変更を加えない。また、basic_stringにもreserveはあるものの、vectorとは性質が違うので、この提案では何もしない。

N4525: C++ Standard Library Issues Resolved Directly In Lenexa

Lenexa会議で解決された標準ライブラリの小粒な問題集。

[PDF注意] N4526: Towards improved support for games, graphics, real-time, low latency, embedded systems

「ゲーム、グラフィック、リアルタイム、低レイテンシー、組み込み系のサポートの改良に向けて」と題された壮大な論文。

内容は、N2271のEASTLを検証するものとなっている。EASTLはEAが自社内で設計して使っているSTL風のライブラリで、ゲーム用にパフォーマンスを重視した設計になっている。

[PDF注意] N4527: Working Draft, Standard for Programming Language C++

C++の最新のドラフト

N4528: Editor's Report -- Working Draft, Standard for Programming Language C++

C++ドラフトの編集者による報告書。

今回の変更点はshared_mutexか。

N4529: C++ Extensions for Library Fundamentals, Version 2, Working Draft

Library Fundamentals TSのドラフト。様々なこれまでに提案されて可決された比較的小粒なライブラリが含まれている。

N4530: Editor's Report — Library Fundamentals TS

Library Fundamentals TSドラフトの編集者の報告書。

ドワンゴ広告

KADOKAWA系列のenterbrainから出版されているニンジャスレイヤーが社内に転がっているので、最近、ニンジャスレイヤーの面白さに目覚めた。

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

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

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

2015-07-13

C++標準化委員会の文書のレビュー: N5410-N5419

N4510: Minimal incomplete type support for standard containers, revision 4

vector, list, forward_listに対して、非完全形を要素型に認める提案。

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

struct Node
{
    std::vector< Node > nodes ;
    // ...
} ;

クラスは定義の終了を持って完全形となるので、この場合のvectorに渡すNode型は不完全型である。つまり、sizeofが取れないなどの問題がある。しかし、不完全型をサポートする実装は可能であり、このコードは実装によって通ったり通らなかったりしていた。

上記のパターンのコードは利用価値があることから、これを認める提案。まず、最も無難なコンテナーに限って認める。

N4511: Adding [nothrow-]swappable traits (Revision 1)

<type_traits>にstd::is_swappable<T>, std::is_swappable_with<T, U>, std::is_nothrow_swappable<T>, std::is_nothrow_swappable_with<T, U>を追加する提案。

N4512: Multidimensional bounds, offset and array_view, revision 7

連続したストレージを多次元配列に見せかけるラッパーライブラリ、array_viewの提案。前回の提案N4494に比べて、細かな変更が加えられている。

[PDF注意] N4513: Technical Specification for C++ Extensions for Transactional Memory

トランザクショナルメモリーTSのドラフト

[PDF注意] N4514: Technical Specification for C++ Extensions for Transactional Memory

トランザクショナルメモリーTS。内容はドラフトと同じ。

N4515: Editor's Report: Technical Specification for C++ Extensions for Transactional Memory

トランザクショナルメモリーの編集者による変更点の報告書。

[PDF注意] N4516: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4516.pdf

ライブラリベースの型安全なunionライブラリ、variantの提案。boost.variantの機能削減版といったところだ。

なお、このvariantは空状態を許容する。理由は、別の型のオブジェクトを代入された時に、元の型のオブジェクトを破棄した後で、代入に失敗した時の状態をどうするのかと考えると、空の状態を許容する設計になったそうだ。

[PDF注意] N4517: Record of Response: National Body Comments ISO/IEC PDTS 19841

トランザクショナルメモリーTSに対するNBコメントに対する返答。

N4518: Make exception-specifications be part of the type system, version 2

例外指定を型の一部に含める提案。現状では、例外指定はポインター同士の代入を制限すると規定されている。しかし、ポインターのポインターを介せば、例外の異なる関数へのポインター型が相互に代入できてしまう。

たとえば、core issue 92は以下のようなコードを問題視している。

void (*p)() throw(int);
void (**pp)() throw() = &p;   // not currently an error

これに対し、対応はしないと結論したものの、やはりなにかおかしい。

N4519: Source-Code Information Capture

ソースファイルの情報を取得できるリフレクションライブラリの提案、__LINE__などのようなプリプロセッサーで取得していた情報が、まともな方法で取得できるようになる。

#include <experimantal/source_location>

int main()
{
    auto sl = std::experimental::source_location::current() ;

    std::cout
            << sl.line() << '\n'
            << sl.column() << '\n'
            << sl.file_name() << '\n'
            << sl.function_name() << std::endl ;
}

source_location::currentは、呼び出した場所のsource_locationオブジェクトを返すconstexpr staticメンバー関数である。

なお、source_location::currentをデフォルト実引数で呼び出した場合、呼び出し元の情報が得られる。


void logger( std::experimantal::source_location sl = std::experimental::source_location::current() )
{
    // slにはlogger関数を呼び出した元の情報が入る。
}

ドワンゴ広告

最近、ドワンゴがかなりガチな条件で3DCGエンジニアを募集しているようだ。

【新規事業】3DCGエンジニア(正社員)|募集職種一覧|採用情報|株式会社ドワンゴ

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

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

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

御岳にクライミングに行ってきた

週末に、御岳にクライミングに行ってきた。

ボルダリングを初めてはや半年、先日はトップロープも経験したので、そろそろ外壁にも挑戦してみたいと思っていた折から、同僚が何人か、週末に御岳に向かうとのころで、同行した。

朝、ホリデー快速おくたまに揺られながらThe Great Gatsbyを読みつつ御岳まで向かう。

駅を出てしばらく歩き、川に降りると、有名な忍者と呼ばれる岩に着いた。すでに先客が何人も登っている。

早速筆者も、忍者返しと呼ばれる一級課題に挑戦したが、左手の初手すら取れなかった。

疲れて木陰となっていた岩の上で寝ていたら、同僚に生贄に捧げられていた。

さて、忍者岩を後にした我々は、次にデッドエンドと呼ばれる岩に向かった。

デッドエンド自体は、当然ながら初手すら取れなかった。

デッドエンドの脇に、イギリス人のトラバースと呼ばれる二級課題がある。これに挑戦した。どうしてもヒールが離れてしまう。

初めての外岩は、何も登れていないのに疲労が激しかった。また指皮の消耗も激しい。最低一級から始まる課題が多い。また、手はともかく足の置き場がない。

それにしても気になったのは、タバコを吸うバカが多いということだ。滅んで欲しい。

2015-07-10

C++標準化委員会の文書 2015-05 post-Lenexaのレビュー: N4501-N5409

N4501: Technical Specification for C++ Extensions for Concurrency, Working Draft

同期まわりの標準ライブラリに対する拡張TS、futureの改良、latch/barrierライブラリ、アトミックスマートポインター。

[PDF注意] N4502: Proposing Standard Library Support for the C++ Detection Idiom, V2

void_tを使ったdetection idiomのためのライブラリを追加する提案の改訂版

前回のN4436と比べて、具体的な文面案が追加されているようだ。

[PDF注意] N4505: Working Draft, Technical Specification for C++ Extensions for Parallelism

並列版アルゴリズムライブラリであるParallelism TSのドラフト。既存のアルゴリズムと同じインターフェースにポリシーを指定すると並列実行してくれる。

[PDF注意] N4506: Parallelism TS Editor's Report

Parallelism TSの編集者による変更点の記述。

[PDF注意] N4507: Technical Specification for C++ Extensions for Parallelism

Parallelism TSの文面。内容なN4505と同じ。

N4508: A proposal to add shared_mutex (untimed) (Revision 4)

C++11のshared_mutexは、C++14でshared_timed_mutexに改名された。C++11のshared_mutexは、実際にはtimed lock要件を満たす必要があるためである。さて、開いたshared_mutexに、timed lockではなく、素のLockable要件のみを満たすものを追加しようという提案。

N4509: constexpr atomic<T>::is_always_lock_free

atomicの実装は、クリティカルセクションのようなロックを必要とする実装であっても、規格準拠である。これは、ロックフリーのアトミック操作を直接提供していないアーキテクチャ上でもatomicを実装可能であり、移植性の向上につながる。

しかし、プログラマーは実装がロックフリーかどうかを知って、それによって実装を切り替えたがるものだ。規格はその需要を満たすために、bool atomic<T>::is_lock_freeメンバー関数を提供している。また、ATOMIC_..._LOCK_FREEマクロもある。

問題は、実装が常にロックフリーかどうかは、コンパイル時にわからないこともある。そこで、マクロの値は、0,1,2のいずれかを取り、それぞれ、ロックフリーではない、条件付きでロックフリー、常にロックフリーという意味を持つ。

このため、常にロックフリーであることを示す、SFINAEで使いやすいconstexperメンバー関数、constexpr bool atomic<T>::is_always_lock_freeを追加しよう

ドワンゴ広告

チャーハンと名乗る同僚がおすすめするうまいチャーハンを出す悟空という店に行ってきた。名にし負うチャーハンが推薦するチャーハン屋なのだから、さぞかしうまいであろうと期待していたところ、実際にうまかった。ただし量が多すぎる。また、完全禁煙ではないので二度と行かない。

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

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

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

Hacking Teamから流出したとされるコードにブラウザーヒストリーの改変をするためとおぼしきものが発見される

国家の諜報機関に攻撃的なリモート操作ツールを売りつけている極めて非人道的な商売をしているHacking Teamから、400GBものデータが流出したという真偽不明のニュースが流れている。流出したデータの中には、FlashやSELinuxのゼロデイ脆弱性が含まれていることが発見されている。

さて、その流出したコードのなかに、ブラウザーのヒストリーを改変すると思しきコードが含まれていて話題になっている。

rcs-common/file.rb at 38290d4eab2b2c295bea021429848a3666647827 · hackedteam/rcs-common

URLを指定しなかったときのデフォルトが、["C:\\Utenti\\pippo\\pedoporno.mpg", "C:\\Utenti\\pluto\\Documenti\\childporn.avi", "C:\\secrets\\bomb_blueprints.pdf"].sampleなどとなっていて、何やらユーモアと悪意と恐怖を感じる。

そのデフォルトのプレイスホルダー的な文字列や、evidenceという単語からみて、証拠を偽造する目的のように思えてくる。

流出したデータの信頼性が怪しいので、本当のところはわからない。

2015-07-07

C++標準化委員会の文書 2015-05 post-Lenexaのレビュー: N4483-N4499

[PDF注意] N4483: Read-copy-update

Linuxカーネルで多用されているRCU(Read-Copy-Update)の解説文書。

N4484: C++ Standard Library Active Issues List
N4485: C++ Standard Library Defect Report List
N4486: C++ Standard Library Closed Issues List

標準ライブラリの既知の問題集

N4487: Constexpr lambdas

constexpr lambdaの提案。

lambda式のクロージャーオブジェクトのデータメンバー、つまりキャプチャする変数の初期化が定数式ならば、定数式のなかで利用できる。

クロージャーオブジェクトがリテラル型ならば、定数式の中で評価できる。

constexpr指定子をlambda式に記述できる。

auto f = []( int x ) constexpr { return x ; }
constexpr int x = f( 1 ) ;

constexpr指定子は省略できる。その場合、lambda式がconstexpr関数の条件を満たせば、関数呼び出し式はconstexprになる。

auto f = []( int x ) { return x ; }
constexpr int x = f( 1 ) ;

クロージャー型の関数ポインター型への変換関数はconstexprになる。

この提案は、lambda式を未評価式の中に記述することを提案していない。つまり、テンプレート仮引数のデフォルトテンプレート実引数に使ってSFINAEトリックに使うことはできない。

Clangベースの実験的実装が公開されている。

https://github.com/faisalv/clang/tree/constexpr-lambdas

N4488: Responses to PDTS comments on Transactional Memory, version 2

トランザクショナルメモリーTSに対するPDTSコメントに対する返答。

日本からは、JP1として、トランザクショナルメモリーがmath.hに対してトランザクショナルセーフを要求しているので、対応のためにパフォーマンスの低下が懸念されるとコメントを送ったが、回答は、math.hは明確に除外されているとしてリジェクトされた。

math.hが明確に除外されている文面について、日本は把握していない。

JP2として、関数のローカルstatic変数の初期化がアトミックに行われるべきだと主張したが、これもトランザクショナルセーフで定める範囲ではないとしてリジェクトされた。

N4489: WG21 2015-04-24 Telecon Minutes

4月24日に行われた電話会議の議事録。

N4490: WG21 2015-05 Lenexa Minutes

5月4日から9日にかけてLenexaで行われた会議の議事録。

[PDF注意] N4491: PL22.16 2015-05 Lenexa Minutes (Draft)

N4490のドラフトと見える。内容はほぼ同じ。

[PDF] N4492: Thoughts about C++17

Bjarne StroustrupによるC++17の考察。

ドラフト版の翻訳をすでに行っている。

本の虫: D4492: Bjarne StroustrupによるC++17の考察の翻訳

N4494: Multidimensional bounds, offset and array_view, revision 6

連続したストレージを多次元配列に見せかけるarray_viewライブラリの提案。前回からの変更点は、一部の識別子の変更や文面の変更など。

N4495: Smart Objects, an alternative approach to overloading operator dot

operator .をオーバーロードする機能の提案。N4477とは設計が違う。

N4477のoperator .は、何らかのリファレンスを返すものであった。

// N4477提案
struct Callable
{
    template < typename ... Types >
    void operator () ( Types ... args ) { }
} ;

struct X
{
    Callable c ;

    Callable & operator . ( )
    {
        return c ;   
    }
} ;

int main()
{
    X x ;
    x.foo() ;
    x.bar( 1, 2, 3 ) ;
}

何らかのリファレンスを返さなければならないということは、結構面倒な制約だ。第一、そのリファレンスが保持された場合どうするのか? その寿命がいつまで存続するのかは、operator .の実装次第だ。

// 寿命はいつまで?
auto ref = x.member ;

N4495では、operator .にコンパイラーが生成する関数オブジェクトが実引数として渡される。

たとえば、

x.some_name ;

と書いて、xにsome_nameというメンバーが存在しない場合、

x.opeator .( synthesized_function_type{} ) ;

というコードに変換される。synthesized_function_typeはコンパイラーにより生成される型で、以下と同等のものになる。

struct synthesized_function_type {
    template<class T>
    auto operator()(T&& t) -> decltype(t.some_name) noexcept(t.some_name) {
        return t.some_name;
    }
};

some_nameに対してintの値を返したい場合、これを受けるxのoperator .は、テンプレートを使って以下のように書ける。

struct some_name_t
{
    int some_name = 0 ;
} ;

struct X
{
    some_name_t data ;

    template < typename T >
    auto operator . ( T && t )
    {
        return t( data ) ;
    }

} ;

メンバー関数呼び出しの場合、実引数に渡す式は、コンパイラーが関数オブジェクトを構築する前に評価される。rvalue性は正しくforwardされる。


x.some_name( a, foo(), foo() ) ;

は、以下のように変換される。

x.operator.(synthesized_function_type{a, foo(), foo()});

コンパイラーによって生成されるsynthesized_function_typeは、以下のようになる。

struct synthesized_function_type {
    // `a' or `foo' may not be visible in that context
    // used here lexically just for demonstration purposes
    typedef decltype((a)) T0;
    typedef decltype(foo()) T1;
    typedef decltype(foo()) T2;
    T0 a0;
    T1 a1;
    T2 a2;

    template<class T>
    auto operator()(T&& t) -> decltype(t.some_name(static_cast<T0&&>(a0), static_cast<T1&&>(a1), static_cast<T2&&>(a2))) noexcept(t.some_name(static_cast<T0&&>(a0), static_cast<T1&&>(a1), static_cast<T2&&>(a2))) {
        return t.some_name(static_cast<T0&&>(a0), static_cast<T1&&>(a1), static_cast<T2&&>(a2));
    }
};

コンパイラーによって生成される関数オブジェクトに、メンバー名の文字列やメンバー関数であるかどうかを取得できるリフレクション機能をつける拡張も将来的に追加できる設計となっている。例えば、リフレクションをサポートする例として、以下のような関数オブジェクトが生成される。

struct synthesized_function_type {
    template<class T>
    auto operator()(T&& t) -> decltype(t.some_name) noexcept(t.some_name) {
        return t.some_name;
    }

    static constexpr const char* name() { return "some_name"; }
    static constexpr bool is_member_function = false;
};

うーむ・・・やりたいことはわかるのだが、この設計はもう少しなんとかならないものか。

N4496: WG21 2014-11 Urbana Minutes (revision 1)

2014年11月3日から8日にかけてUrbanaで行われた会議の議事録の改訂版とみられる。

[PDF注意] N4497: PL22.16 2014-11 Urbana Minutes (Final)

上記議事録の最終校のようなタイトル。

N4498: Variadic lock_guard (Rev. 2)

lock_guardをVariadic Templatesを使い、任意個のロックを管理できるようにしようという提案。

これまで、複数のLockable要件を満たす型をロックするのに

std::mutex m1, m2 ;

void f()
{
    std::lock( m1, m2 ) ;
    std::lock_guard< std::mutex >( m1, std::adopt_lock ) ;
    std::lock_guard< std::mutex >( m2, std::adopt_lock ) ;
}

のようなコードを書かなければならなかったが、N4498提案では、

void f()
{
    std::lock_guard< std::mutex, std::mutex >( m1, m2 ) ;
}

と書くだけでよい。

[PDF注意] N4499: Draft wording for Coroutines (Revision 2)

コルーチンのドラフト。まだまだ色々変更がありそうなので詳細に読む気にならない。

ドワンゴ広告

最近、社内で計算方法が厳密に規定されているdistributionクラスが標準ライブラリに欲しいという話がでている。デバッグ目的で全く同一の乱数列を移植性の高い方法で生成したい。C++の乱数ライブラリは、生の乱数を生成するエンジンと、乱数を目的の範囲の値に分布させるディストリビューションに分かれている。エンジンクラスの乱数の生成方法は厳密に規定されているが、ディストリビューションクラスの実装方法は規定されていない。

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

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

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

2015-07-06

ボルダリング半年

去年の12月頃から、ボルダリングを始めた。そろそろ半年はたった計算になる。

ボルダリングを始めたきっかけは、社内にボルダリングの同好会があったためだ。

最初は、30分ほどで腕が疲れて登れなくなるし、ボルダリングをした後は4日間ほど筋肉痛になっていたが、週一でボルダリングをしていると、筋肉痛になることはなくなったし、数時間続けることができるようになった。これは単純に筋力がついたのと、効率的な体の動かし方を覚えたためだろう。

かわりに、今度は肘や股関節などの関節痛になることが多くなった。これは、ボルダリングをしばらく休んで休息する以外にない。関節痛を感じたら、ボルダリングは一週間ほど控えるようにしている。

ところで去年、ボルダリングを始める直前に予備自衛官の訓練に行っていて、その体力検定で握力を図っているのだが、先日の 予備自衛官の訓練で握力を測定したところ、左右ともに10kgほど上がっていることが確認できた。

また、前腕に筋肉が着いたのか、以前より少し盛り上がっている。

さて、ボルダリングには、独特のクライミングシューズを用いる。クライミングジムではレンタルシューズを貸し出しているが、やはり自分のシューズがほしい。筆者は初めてそうそうにシューズを買った。

一足目に買ったのはスポルティバのタランチュラ(39.5)だ。履きやすく、無難な形をしていて、安いので、初心者が一足目に買うにはおすすめできる。ただ、慣れるまで足が痛かった。

三ヶ月ほどでつま先のソールが破れてしまったので、次のシューズを買うことにした。

二足目に買ったのはスポルティバのソリューション(39.5)だ。上級者がコンペなどでも使っているシューズで、値段もお高い。ただ、今のクライミングシューズの価格帯が、1万5千円から2万円ぐらいなので、差額はせいぜい5千円。どのシューズを買ってもあまり変わらない気がすると考え、買ってみた。

つま先の先端だけで極小のホールドの上に立てるし、ヒールの形状がすばらしく、ヒールフックがとてもやりやすくなった。ただ、スメアリングがしにくくなった。

基本的に素晴らしいシューズだったのだが、自分の足で登っている感覚があまり感じられない靴だった。やはりこれも3ヶ月でつま先のソールが破れてしまった。前のタランチュラも、今回のソリューションも、左のつま先のソールが破れている。おそらく左足の動きが下手で引きずるから敗れるのではないかと指摘された。

やれやれ、足の使い方が未熟であるために靴がすぐ痛むのは辛い。

さて、三足目を買わなければならない。前述の通り、クライミングシューズの価格帯は最低でも1万5千円、高くても二万円代なので、価格で選ぶ必要はない。

三足目には、足裏感覚がわかる靴を買おうと考えた。また、靴のサイズを攻めすぎずに、指の力を鍛えられるものにしたい。タランチュラもソリューションも、血が通わないくらいサイズがきつかったので、どうも足の指に力が入りにくかった。

色々と検討した結果。三足目にはスポルティバのジーニアス(40.0)を買った。このシューズにはエッジがなく、つま先の一点ではなく、面を押し付けてホールドに乗る。スメアリングもしやすい。レースアップなので着脱が煩わしくないかと懸念していたが、そんなことはなかった。靴ヒモで足の形にピッタリと合わせられるので、とても快適だ。

この靴は三ヶ月以上持ってほしいものだ。

さて、靴の次はチョークだ。手指が汗で滑ってはホールドをつかめない。そのために、クライミングではチョークを使う。チョークには液体チョークと粉チョークがある。液体チョークは強力に滑りにくくなるが、終わった後に手を洗ってもなかなか落ちない。指の皮膚へのダメージも大きいように思う。粉チョークは、すぐになくなるので、頻繁につけなければならない。

筆者は最初、マンムートの液体チョークを使っていたが、今は粉チョークを使っている。

さて、ジムでのボルダリングは、たいてい数メートルぐらいの壁を登るのだが、ロープを使って高い壁を登ることができるジムもある。ロープにはトップロープとリードとがある。

先日、ロープができるジムに行き、ビレイの講習を受けて、トップロープで登ってみた。なかなか面白い。パートナーが必要なので、それほど頻繁にできないのが残念だが、これからも機会があればロープをしたいものだ。誰か一緒に行けるロープ仲間を確保すべきか。

私が行った錦糸町のTウォールは、ロープに必要な機材がすべてレンタルできるが、ATC、カラビナ、ハーネスは、いずれ買おうと思う。

2015-07-02

C++標準化委員会の文書 2015-04-pre-Lenexaのレビュー: N4470-N4482

Variadic lock_guard

std::mutexなどのlock/unlockするオブジェクトが複数ある場合は、ロックする順番を工夫しないと、デッドロックしてしまう。そこで、標準ライブラリには、ロックする順番を実装依存の方法でデッドロックを起こさないようにしてくれるstd::lockがある。

また、標準ライブラリには、std::lock_guardという、RAIIラッパーがある。

問題はこの2つを組み合わせるのが結構ダルい。

std::mutex m1, m2 ;

void f()
{
    std::lock( m1, m2 ) ;

    std::lock_guard<std::mutex> l1( m1, std::adopt_lock ) ;
    std::lock_guard<std::mutex> l2( m2, std::adopt_lock ) ;
}

そのため、lock_guardをVariadic Templatesにして、任意個のlockを受け取れるようにする提案。

std::lock_guard< std::mutex, std::mutex > l( m1, m2 ) ;

ぜひ入るべきだ。

N4471: Template parameter deduction for constructors (Rev. 2)

クラステンプレートのコンストラクターからテンプレート実引数を推定する提案。

template < typename T >
struct S
{
    S( T ) ;
} ;

// めんどくさい
S<int> s1(0) ;
// N4471提案
S s2(0) ; // S<int>

ぜひ入って欲しい。

ただし、単純にコンストラクターから推定できない場合もある。

vector<X> v1 = { ... } ;
auto v2 = vector( v1.begin(), v1.end() ) ; // v2はvector<X>になってほしい

この場合は推定できない。提案では、typed constructorを導入するという案がある。

template<typename T, typename Alloc = std::allocator<T>> struct vector {
  // Option 1: Typed constructor in primary template only
  template <typename Iter> vector<iter::value_type>(Iter b, Iter e);
};
// Option 2: Typed constructor given globally
template<typename Iter> vector<typename iterator_traits<Iter>::value_type>(Iter b, Iter e);
template<typename Iter> vector(Iter b, Iter e) -> vector<typename iterator_traits<Iter>::value_type>

これはちょっとやり過ぎな感がある。

N4472: constexpr goto

constexpr関数の中でgotoの使用を認める提案。

現在、constexpr関数の中でgotoを使うことはできない。しかし、条件分岐やループは使うことができる。gotoが使えないのは本当に技術上の制約なのか。はた、単なる好みの問題なのか。ネストされたループから抜けるにはgotoを使うのが最も手っ取り早いし、広く使われている。gotoは本当に禁止すべきなのか。

N4473: noexcept(auto), again

noexcept(auto)復活論。

noxcept(auto)例外指定は、関数の本体が例外を投げる可能性があればnoexcept(false)に、例外を投げなければnoexcept(auto)になる。

[PDF注意] N4474:Unified Call Syntax: x.f(y) and f(x,y)

統一関数呼び出し記法の提案。

x.f(y)に対して、もし呼び出しが妥当ではない場合、f(x,y)を試みる。

p->f(y)に対して、もし呼び出しが妥当ではない場合、f(p,y)を試みる

f(x,y)に対して、もし呼び出しが妥当ではない場合で、xに対して->が定義されている場合、x->f(y)を試みる。そうでなければx.f(y)を試みる。

begin/end/swapと言った共通の処理をするのに、メンバー関数で実装されているのかフリー関数で実装されているのかがわからないため、。ジェネリックコードから使いにくいという問題を解決する。

ただし、これを真面目に考えると、"hello".puts()や2.0 .sqrt() (スペースは必要)も合法になる。

std::FILE *型の変数fpにたいして、fp->fclose()などが呼び出せるので、静的解析ツールによる補完がやりやすくなるという意見もあるが、for_eachなども補完されてしまうの、果たして便利だろうか。論文はこの懸念を載せていないが。

[Bjarneは論文をPDFで書くのをやめろ] N4475:Default comparisons (R2)

デフォルトの比較演算子を暗黙に生成する機能の提案。

クラスのデータメンバーが比較可能なとき、クラスのメンバーごとの比較を行う比較演算子を自動で生成できる機能。

ポインター型のデータメンバーがある場合は==と!=を生成しない。mutableは比較しないという、批判論文の意見は無視した形の提案となっている。

私はポインターもmutableメンバーも等しく評価されるべきだと思う。

[Bjarneは論文をPDFで書くのをさっさとやめろ ] N4476: Thoughts about Comparisons (R2)

比較演算子の自動生成に対する様々な戦略について考察している。

[BjarneはとにかくPDFをやめろ] N4477: Operator Dot (R2)

operator .をオーバーロードできるようにする提案。プロクシークラスが書けるようになる。

N4478: Networking Library Proposal (Revision 5)

ネットワークライブラリの提案。Boost.Asioが土台になっている。

N4479: Merge Fundamentals V1 into V2

提案されているライブラリ拡張のLibrary Fundamentals V2をV1にマージするという文書。NB投票の際に混乱を防ぐためにV1とV2は分割していたそうだ。

N4480: C++ Extensions for Library Fundamentals, DTS

N4481: C++ Extensions for Library Fundamentals, Version 2, Tentative Working Draft

ライブラリ拡張提案のドラフト

N4482: Some notes on executors and the Networking Library Proposal

ネットワークライブラリにおけるexecutorについて、別の論文で提案されている、軽量実行媒体との用語のすり合わせや、最新の会議での合意内容とのすり合わせ、また先行研究への言及。

ドワンゴ広告

毎週木曜日はドワンゴのボルダリング部の活動日。最近、4級が登れるようになってきた。

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

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

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

C++標準化委員会の文書 2015-04-pre-Lenexaのレビュー: N4460-N4469

N4460: LWG 2424: Atomics, mutexes and condition variables should not be trivially copyable

atomic, mutex, condition variableは、コピーができない。ただし、現行の規格の定義に従えば、trivially copyableになってしまう。

これらのクラスは、コピー代入演算子を明示的にdeleted定義されているが、それだけではtrivially copyableの条件から逃れられない。しかし、コピー代入演算子をdeleted定義すればtrivially copyableにならないと規定してしまうと、以下のようなクラスがtrivially copyableではなくなってしまう。

struct X
{
    const int val ;
} ;

このクラスは暗黙にコピー代入演算子がdeleted定義される。このクラスはtrivially copyableであるし、その挙動は変えたくない。

明示的なdeleted定義と暗黙のdeleted定義の意味を変えるという方法は、明示と暗黙の違いをできるだけなくしたいという点から、採用できない。

is_trivially_copyableとis_trivialに特殊化を記述する汚い方法はやりたくない。

論文では、規格の文面上、trivially copyableではないと記述する方法を提案している。

N4461: Static if resurrected

static ifの提案

static ifは少し前までかなり真剣に議論されていて入るかもしれないような雰囲気だったのだが、コンパイラー実装者の強い反対にあったため規格には入らなかった。

ここで提案されているstatic ifには、前回提案されていたものに比べて制約が多い。

  • ブロックスコープのみ
  • 新しいスコープを作る
  • 片方ブランチがwell-formedとなる条件部の値がどちらのブランチに対しても存在する。

GCCのRichard Smithによると、

N3329の「問題ある」部分は、

1) 新しいスコープを作らない

2) 選択されなかった方のブランチは完全に無視される(トークン列はパース可能でなくても構わない)

これは、少なくとも2つの有名なコンパイラーの実装で使われているテンプレートモデルと根本的に非互換である。

もし、static ifが(このスレで提案されているように)新しいスコープを導入し、static ifのどちらの分岐もインスタンス化可能であるならば(つまり、テンプレートのトークン列と同じ制約)、コンパイラー実装者の、俺の屍を越えて行けレベルの反対はなくなるだろう。

そのため、この論文で提案されているstatic ifは、Richard Smithの提示した制約を受け入れている。

なぜstatic ifは必要なのか。例えば、パラメーターパックを展開したいとすると、以下のようにオーバーロードを書かなければならない。

template <class T> 
void f(T&& t) 
{
    /* handle one T */
} 

template <class T, class... Rest> 
void f(T&& t, Rest&&... r) 
{
    f(t); 
    /* handle the tail */
    f(r...); // I think I have a bug here if I don't have a zero-param overload
}

これはstatic ifがあればもっと簡単に書ける。

template <class T, class... Rest> 
void f(T&& t, Rest&&... r) 
{
    /* 
      Tの処理
    */
    static_if (sizeof...(r)) {
    /*
      残りの処理
    */
        f(r...); // ゼロ引数のオーバーロードは必要ない。
    }
}

ある条件を満たすかどうかでコンパイル時に実装を切り替えるのも、とても簡単になる。現在はこう書かなければならないが、

template <class T, class... Args> 
enable_if_t<is_constructible_v<T, Args...>, unique_ptr<T>> 
make_unique(Args&&... args) 
{
    return unique_ptr<T>(new T(forward<Args>(args)...));
}  

template <class T, class... Args>  
enable_if_t<!is_constructible_v<T, Args...>, unique_ptr<T>>
make_unique(Args&&... args) 
{
    return unique_ptr<T>(new T{forward<Args>(args)...});
}

static ifがあれば、以下のように書ける。

template <class T, class... Args> 
unique_ptr<T>
make_unique(Args&&... args) 
{
    static_if (is_constructible_v<T, Args...>) {
        return unique_ptr<T>(new T(forward<Args>(args)...));
    } else {
        return unique_ptr<T>(new T{forward<Args>(args)...});
    }
}

明らかに簡単だ。

コンセプトでも問題は解決できるが、定義が分散してしまい極めて読みにくいコードになる。また著者はコンセプトとstatic ifを組み合わせるとオーバーロードを書かずにすむと主張している。

template <typename T, typename U> void f(T, U)
  requires C1<T> && (C2<U> || C3<U>)
{
    static_if (C2<U>) 
    {
    } 
    else if (C3<U>) 
    {
    }
}

なるほど、確かにこれは便利だ。

N4462: LWG 2089, Towards more perfect forwarding

何らかの簡単なコンパイル時ディスパッチの必要性を訴える論文。

make_unique, make_shared, allocator::constructといったファクトリー関数は、アグリゲートをうまく扱うことができない。

struct X { int a, b, c ; } ;

int main()
{
    // OK、アグリゲート初期化
    std::unique_ptr<X> p1( new X{1,2,3} ) ;

    // エラー、呼び出し可能なコンストラクターがない。
    auto p2 = std::make_unique<X>( 1, 2, 3 ) ;
}

これはなぜかというと、allocator::constructが、以下のようになっているためだ。

template < typename U, typename ... Args >
void allocator::construct(U * p, Args && ... args ) 
{
    return new( static_cast<void *>(p) ) T( std::forward<Args>(args)... ) ;
}

このままではアグリゲート初期化できない。しかし、一律リスト初期化{}にするのも問題だ。

LWG2089では、以下のような修正を提案している。

  • もし、is_constructible_v<TargetType, Args...>がtrueであれば、直接非リスト初期化を行う。
  • そうでなければ、初期化リストを使う。

これにより、最初の例が動くようになる。

この変更は、ライブラリでアグリゲートが使えるようになるし、実行時オーバーヘッドもないし、既存のコードもほとんど壊さないだろうし、ビルド時間もさほど増えないだろうし、実装は簡単だし、言語側での変更も必要ない。

要するに、この変更は望ましいものであって、さっさと規格入り作業を粛々と進めろとしか言う他ない。

コンパイラーベンダーが標準ライブラリにこれを実装することは慣れているので簡単だ。だがしかし、普通のユーザーが同じことをしたいとしたらどうするだろうか。

[超怖い話BEGIN] それには、非型boolテンプレート仮引数を取るクラステンプレートのstaticメンバー関数テンプレートにデリゲートし、クラステンプレートをfalseの場合に対して特殊化し、is_constructibleの結果によってディスパッチさせる[超怖い話END]

// 超怖い話の実装
template < bool >
struct construct_impl
{
    template < typename U, typename ... Args >
    static auto invoke( U * p, Args && ... args )
    {
         return new( static_cast<void *>(p) ) U( std::forward<Args>(args)... ) ;
    }
} ;


template < >
struct construct_impl<false>
{
    template < typename U, typename ... Args >
    static auto invoke( U * p, Args && ... args )
    {
         return new( static_cast<void *>(p) ) U{ std::forward<Args>(args)... } ;
    }

} ;

template < typename U, typename ... Args >
auto construct(U * p, Args && ... args ) 
{
    return construct_impl< std::is_constructible< U, Args ... >::value >::invoke( p, std::forward<Args>(args)... ) ;
}

あるいは、[超怖い話BEGIN] true_typeかfalse_typeかでタグ付けしたオーバーロードでディスパッチする[超怖い話END]

// 超怖い話の実装
template < typename U, typename ... Args >
auto construct_impl( std::true_type, U * p, Args && ... args )
{
     return new( static_cast<void *>(p) ) U( std::forward<Args>(args)... ) ;
}

template < typename U, typename ... Args >
auto construct_impl( std::false_type, U * p, Args && ... args )
{
     return new( static_cast<void *>(p) ) U{std::forward<Args>(args)... } ;
}

template < typename U, typename ... Args >
auto construct( U * p, Args && ... args )
{
    return construct_impl( typename std::is_constructible< U, Args ...>::type{}, p, std::forward<Args>(args)... ) ;
}

超怖い話は、そのままコードに落とせば動くぐらい、メタプログラミングにおけるコンパイル分岐の手法を簡潔にまとめている。さて、ユーザーも同じことをしたくなった時のために、この手法を教育しなければならないのだろうか。この手法は一般人が書けるだろうか? 書けないものはC++プログラマー失格なのだろうか?

論文筆者は、我々には何らかのコンパイル時ディスパッチを簡単にする方法が必要であると提案している。

static ifが入れば簡単に書けるようになりそうだ。

[PDF注意] N4463: IO device requirements for C++

イテレーター要件とかコンテナー要件などのように、IOデバイス要件を定める提案。

デバイスとの入出力の方法、デバイスの設定可能な項目の取得、デバイスの設定状態の取得と変更、デバイスの機能一覧の取得などが行える。

具体的にサポートするデバイスもないのにそんな要件だけ定めてなにか意味があるのだろうか。

[PDF注意] N4464: Pi-calculus syntax for C++ executors

π-calculusをC++で実現した論文。λ計算がシーケンシャルな処理をすべて記述できる計算力を持っているように、π-calculusも並列処理をすべて記述できる計算力を持っている

だが、誰が使うんだ? なんでC++標準化委員会の文書として公開されているのか理解できない。コンピューターサイエンスの理論としては興味深いものがあるだろうが、π計算の演算子をC++に持ち込んでも、まったく実用的だとは思えない。

N4465: A Module System for C++ (Revision 3)

モジュールの提案。

#includeの代替機能。プリプロセッサーはなくなるのではなくて共存する。

[PDF注意] N4466: Wording for Modules

モジュールの文面案

提案されているモジュールは、新しいキーワードとしてimportとmoduleを追加する。

ある翻訳単位をモジュールとするには、モジュール宣言を記述する必要がある。

module module-name ;

と記述する。module-nameは、識別子か、"モジュール名 . 識別子"となる。これは、std.vectorとかstd.stringとか、lib.math.random.knuthのような名前空間に似たモジュール名の分類を可能にする。

モジュールの中のエンティティを外部から使うには、import宣言しなければならない。

import std.string
import std.iostream

int main()
{
    std::string buf ;
    std::cin >> buf ;
}

モジュールとなる翻訳単位の中のエンティティは、明示的にexportしない限り外部には見えない。

module mylib

export void my_public_function() ;
void my_private_function() ;


// 囲むこともできる
export { ... }

mylibをimportすると、my_public_functionのみが見える。my_private_functionは見えない。別の翻訳単位でmy_private_functionという名前の関数を定義しても、別々の定義であり、ODR違反にならない。

module宣言で翻訳単位をモジュールにする。export宣言で外部に出したいエンティティをマーク。import宣言でモジュールを使う。というだけだ。

[PDF注意] N4468: On Quantifying Memory-Allocation Strategies

グローバルあロケーターに対してローカルなアロケーターはどのような条件でどのようなアロケーター戦略を使えばどのように効率的になるのかということを考察した論文。

なぜかドナルドの絵が引用されている。

N4469: Template Argument Type Deduction

非型テンプレートパラメーターの値を取るときに型も推定する機能を追加する提案。

現行では、以下のようなコードを書かなければならない。

template < typename T, T v > struct S ;

S< decltype(x), x > s ;

テンプレートパラメーターとして何らかの型の値を取りたいということは、まず型引数を得た上で、その型の値を取らなければならない。そのようなテンプレート使う側は、まず型を渡して、その後に値を渡さなければならない。ある値xがある場合は、decltypeでその型を得るのが最も手っ取り早い。

しかし、これは明らかに面倒だ。以下のように書きたい。

S<x> s ;

コンパイラーはxの型を推定できるのであるから、推定して欲しい。

さて、この機能をどのように実現するかについて、文法的に意見が分かれている。

最も簡単なものは、usingキーワードを使う文法だ。

// Tは推定される
template < using typename T, T v > struct S ;

このようにusing typenameと書くだけで、Tは推定される。

この文法の問題点は、仮引数と実引数の順序がずれるということだ。

template < using typename T, T v, using typename U, U w > struct S ;

S< x, y > s ;

そのため、using typenameは外に出す文法案もある。

template
    using typename T, typename U
    < T v, U w >
    struct S ;

これはテンプレート仮引数とテンプレート実引数の位置関係が対応する。

他にも、autoを使う文法案がある。

template < auto v > struct S ;

using typenameを使うほうが柔軟な型指定ができるが、autoの方が手軽だ。

どちらの文法案も競合しないので、両方入れるという案もあるそうだ。

ドワンゴ広告

社内で挙動が厳格に定義されている移植性に優れたuniform_int_distributionがほしいという声を聞いた。需要はあるのだろうか。

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

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

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

2015-06-30

C++標準化委員会の文書 2015-04-pre-Lenexaのレビュー: N4450-N4459

N4450: Variant: a typesafe union (v2)

型安全unionとして、variantライブラリの提案。

Boost.variantと似ているが、variantのネストはサポートしていない。

[PDF注意] N4451: Static reflection

静的リフレクションとして、メタプログラミングでプログラムの構造を辿れる。

論文の冒頭で、会議で上げられた懸念事項が書いてあるが、筆者も同感で、あまりにも巨大すぎる上に暴力的に強力な機能であると思う。

[PDF注意] N4452: Use cases of reflection

N4451で提案されている静的リフレクションは、あまりにも強力すぎる。初心者にそのような強力なツールを与えることは危険ではないか。という会議での懸念に対して、提案されている静的リフレクションの利用例を挙げている論文。

プログラミングにおいては、機械的な雛形コードを手で書かなければならないことがよくある。プリプロセッサーマクロやテンプレートによるメタプログラミングは、そのようなコードの記述量を抑えることに貢献しているが、限界がある。リフレクションがあれば問題を解決できる。

利用例1: ポータブルな型名

std::type_infoのnameメンバー関数の返す文字列は規格化されていない。それどころか、人間が読める文字列を返すとも、ユニークな文字列を返すとも規定されていない。文字列まで規格化された機能が必要である。さらに、nameメンバー関数はconstexpr関数ではないのでコンパイル時に使えない。また、type_infoはtypedefを考慮しないので、これまたやりにくい。

利用例2: ログ

関数の実行時にログを取るさい、関数の引数名をログ出力に含めたいことはよくある。

利用例3: シリアライゼーション

あるクラスのインスタンスをXMLやJSONやXDRのような構造化されたフォーマットで出力したい。これにはクラスごとに個別でメンバーを列挙するコードを手で書かなければならない。リフレクションがあればこのような問題は簡単に解決できる。

利用例4: Cross-cutting aspects

特定の条件を満たした関数の前後に何らかの共通処理を追加したい場合、リフレクションがあれば冗長なコードを書かずに簡単にできる。

利用例4: factory patternの実装

論文では、追加の利用例として、強力な静的リフレクションを使う利用例を挙げている。

特定のnamespace内にあるpersistent_で始まる変数名からSQLを生成。

コンパイル時にC++ソースコードを生成

デリゲートやデコレートの実装

データメンバーの配置を変える

struct foo
{
    bool b;
    char c;
    double d;
    float f;
    std::string s;
};

このようなクラスを与えると

struct rdbs_table_placeholder_foo
{
    column_placeholder<bool>::type b;
    column_placeholder<char>::type c;
    column_placeholder<double>::type d;
    column_placeholder<float>::type f;
    column_placeholder<std::string>::type s;
};

このようなコードを生成できる。

具体的にコード生成をするリフレクションを使ったコードは、論文を参照。

[PDF注意] N4453: Resumable Expressions

resumable expressionの提案。

Urbana会議以前は、コルーチンとresumable関数というやや似通った性質をもつ2つの機能が提案されていた。そして、2つの機能を統一することで合意していたのだが、スタックレスとスタックフルとはまったく別々の需要を満たすための機能であって、多少の共通項があるとはいえ、独立した機能として別々に議論すべきだということになった。これにより、スタックフルコルーチンは、純粋にライブラリ実装にして、スタックフルコルーチンをライブラリ実装できる軽いスタックレスコルーチンをコア言語に導入すべきだという方向に話が進んだ。統一の話がなくなったのであるから、awaitとかyieldなどのキーワードは不要となった。

resumable expressionsは、constexpr関数にヒントを得て設計された。

constexpr関数は、関数をconstexprであると明示的にキーワードで修飾する。そして、任意の式で呼び出すことができる。

constexpr int twice( int x ) { return x * 2 }

constexpr int a = twice( 2 ) ;
int b = twice( 4 ) ;

普通の式で使うには、関数はconstexpr関数であるかどうかを気にする必要はない。resumable expressionsもこのような設計を参考にしている。

まず、resumableキーワードを用いて、resumable関数を宣言する。

resumable void print_1_to_n( unsigned int n )
{
    for ( unsigned int i = 1 ; i <= n ; ++i )
    {
        std::cout << i << std::endl ;

        break resumable ;
    }
}

中断するところで、break resumableと記述する。

あとは、resumable式から使うだけだ。

int main()
{
    resumable auto r = print_1_to_n( 10 ) ;

    while( !r.ready() )
    {
        std::cout << "resuming ... " ;
        r.resume() ;
    }
}

resumable式は、以下の形で使う。

resumable auto r = expr ;

このときのrの型Rは実装が生成する。Rには、result_type, ready(), resume(), result()がある。

yeildやawaitなどは、resumable式を使ってライブラリで実装できる。

だいぶC++らしい小さなコア言語機能の提案だ。これは悪くなさそうだ。

N4454: SIMD Types Example: Matrix Multiplication

N4184で提案されているSIMD演算を使って行列の掛け算を実装する論文。利用例の例示として書かれた。

N4455: No Sane Compiler Would Optimize Atomics

「まともなコンパイラーはアトミックを最適化したりしない」という都市伝説は間違っていることを説いている論文。

コンパイラーはアトミックも最適化する。この論文では、最適化の例を紹介している。

コンパイラーは、プログラムをas-ifルールで最適化できる。これは、コンパイラーは、オリジナルのコードと挙動が変わらなければ、特定のアトミックを強くしたり弱くしたりできる。

最適化の例として、たとえば、アトミックの中間の値をすっ飛ばす。

void inc(std::atomic<int> *y) {
  *y += 1;
}

std::atomic<int> x;
void two() {
  inc(&x);
  inc(&x);
}

このようなコードを、最適化の結果、以下のようにしてもよい。

std::atomic<int> x;
void two() {
  x += 2;
}

他にも、x86においては、lock付きadd/subをlock付きinc/decに置き換えることも可能だ。

また、アトミックのまわりの処理も最適化の対象になる。

int x = 0;
std::atomic<int> y;
int dso() {
  x = 0;
  int z = y.load(std::memory_order_seq_cst);
  y.store(0, std::memory_order_seq_cst);
  x = 1;
  return z;
}

このコードは、以下のように最適化できる。

int x = 0;
std::atomic<int> y;
int dso() {
  // デッドstore操作の除去
  int z = y.load(std::memory_order_seq_cst);
  y.store(0, std::memory_order_seq_cst);
  x = 1;
  return z;
}

上と似ている以下のようなコードは、

int x = 0;
std::atomic<int> y;
int rlo() {
  x = 0;
  y.store(0, std::memory_order_release);
  int z = y.load(std::memory_order_acquire);
  x = 1;
  return z;
}

以下のように最適化できる(ただし、現在LLVMはこの最適化ができない)

int x = 0;
std::atomic<int> y;
int rlo() {
  // デッドstore操作の除去
  y.store(0, std::memory_order_release);
  // 冗長なloadの除去
  x = 1;
  return 0; // 保存された値がここまで到達
}

loadが除去されるのは、他のスレッドとの同期がないためだ。releaseの次にaquireがきているが、コンパイラーはstoreされた値が改変されないので、その次のloadは冗長だと判断する。

なんだかこの最適化は極めて怖い。

以下のようなコードは変換されない。

int x = 0;
std::atomic<int> y;
int no() {
  x = 0;
  y.store(0, std::memory_order_release);
  while (!y.load(std::memory_order_acquire));
  x = 1;
  return z;
}

論文は最後に、それぞれの立場に対して意見を述べている。

標準化委員会へ:これらの最適化が起こらないと仮定するな。むしろ推奨しろ。よりハードウェアに近い最適化ができる既存の方法を標準化しろ。同期と並列実行をより簡単にできて、失敗しにくいライブラリを提供しろ。

開発者へ:アセンブリを捨てろ。そんなに最適化できないし、そもそもコードを書いている時点で存在するアーキテクチャにしか対応できない。コンパイラーのパフォーマンスが期待通りでないのならばバグ報告を投げろ。標準化委員会に同期と並列実行を実現できる方法を提案しろ。ThreadSanitizerのようなツールをt受かってコード中の競合を発見しろ。

ハードウェアベンダーへ:ハードウェアの能力を示せ。

コンパイラー開発者へ:さっさと仕事にもどれ。まだ最適化できることと・・・ぶち壊れるコードは山ほどある。利用者がいいコードを書けるようにしろ。コンパイラーはアトミックの正しくない使い方を検出したならば、メッセージを吐くべきだ。

N4456: Towards improved support for games, graphics, real-time, low latency, embedded systems

N2771のEASTLの論文を考察している。現在のSTLに足りないもの、やや古い論文なので、現代ではもう意味がなくなったものなどを列挙している。

N4457: C++ Standard Core Language Active Issues
N4458: C++ Standard Core Language Defect Reports and Accepted Issues
N4459: C++ Standard Core Language Closed Issues

コア言語に対する問題集。

ドワンゴ広告

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

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

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

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

シェアハウスとタバコと暴力

以下のようにまとめられている。

「煙草の煙から自身を守るためなら暴力もやむを得ない」のか - Togetterまとめ

何を書いても火に油を注ぎ、単に第三者の余興となるだけなのだが、私(江添)の視点で書いておこうと思う。

まず、妖怪ハウスの間取りについて説明しなければならない。妖怪ハウスにはリビングがあり、その横に和室がある。私はこの和室に住んでいる。リビングと和室に面してベランダが設置してある。このリビングと和室に面したベランダは禁煙である。かつ、室内に煙草の煙が流れこむことや、室内にタバコの吸い殻や灰をばらまくのも、極めて迷惑であり常識がない行為であると同意がなされている。

妖怪ハウスには、喫煙所として定められた、別のもっと大きなベランダがある。

28日の夕方過ぎ、なぜか自室の和室が煙たいことに気がついた。臭いは窓の外からやってくるようである。見ると、リビングと和室に面したベランダでタバコを吸っている見知らぬ人間が二人いる。私はタバコを即座に中止するように、また、家から出て行くように言った。そんなところで煙を発生させる非常識な人間に家に上がることを許可したくはない。

さて、この失礼な二人は、妖怪ハウスの住人である平林の連れてきた客であることが明らかとなった。私は、何故そのような非常識な客を連れてきたのか、非常に迷惑していると平林に言った。この時、私はかなり怒っていたので、声は自然とどなり声になってしまった。平林の返答は、その語句を具体的に覚えていないが、「そう、残念だったね」などと言った極めて責任感のないものであったと記憶している。私は怒りのあまり机をけった。

この後、つかみ合いに発展した。平林に発生した結果が以下の通り。

私側としては、右目の下と首筋に引っかき傷を得た上に、メガネのフレームが曲がった(私のメガネは樹脂製ではなくチタン製なので、割れることはなかった。)

目撃者によると私から手を出したとのことだが、これは間違いで、平林から手を出してきたのだ。私は手を振りほどこうとしていただけだ。私の背の後ろから観測したので、平林の伸ばす手が見えなかったのだろう。メガネを割ったのは意図的ではなく、クビをしめられている最中になんとか身を離そうともがいた結果だ。

なぜか私が殴ったと思い込んでいる者もいるようだが、(メガネが正面から殴られて割れたように見えるからだろうか)私は殴っていない。なんとか首を絞められているのを振りほどこうとしただけだ。

ぐっちょむについて

ぐっちょむはこの場に居合わせておらず、後から私以外の観測者から話を聞いて私に論争をふっかけてきた者である。他人に受動喫煙をさせる可能性のある場合はタバコを吸わないのが当然であるべきなのだが、ぐっちょむはそれに同意していない。ぐっちょむは伝聞を元に尾ひれをつけて事実と異なることを主張するのと、同じ話題を延々とループするので、話が成立しない。ぐっちょむはドラッグをやっているという話があるので、私は関わりたくない(ドラッグを引き合いに出したのは、まともに会話が成立しないからである。)

住人の一人が警察を呼んだというのは、はるしにゃんが私にラップトップを壊されたと言いがかりをつけたことだ。私には全く身に覚えがないばかりか、その壊れたラップトップが存在するのかも知らない。「説明できないということは私が犯人だ」などという謎の論理を持ちだされても仕方がない。

今後

私に受動喫煙させる失礼な客を連れてきた挙句に、掴みかかってくる人間と同居はできないので、私は次の物件を見つけ次第妖怪ハウスを出て行く。7月中に物件を見つけたいものだ。

2015-06-29

そんなにセキュアではないお粗末なNoScriptのホワイトリスト(修正済み)

The NoScript Misnomer - Why should I trust vjs.zendcdn.net? | The Hacker Blog

「俺の環境はNoScriptを入れてるからセキュアだぜ」などと豪語する勘違い野郎に冷水を浴びせるために、デモ可能なNoScriptを迂回する方法を探していた人間が、NoScriptのお粗末なホワイトリスト指定を発見したそうだ。

NoScriptはデフォルトで、非常に有名なドメイン名(CDN、超有名Webサイト等)をホワイトリストに入れている。

しかし、このドメイン名をホワイトリストは、サブドメインもホワイトリストに入ってしまうという問題がある。もしサブドメインとページ内容を第三者が自由に作成できるようなドメインが入っていれば、信頼が破綻する。

さて、リンク先の著者は、まずホワイトリストに入っているドメインのWebサイトのXSS脆弱性を探そうと考えた。ところが、それをするまでもなく、ある重大な発見をした。

なんと、ホワイトリストに入っているドメイン名の一つ、zendcdn.netが誰にも所有されることなく空いていたのだ。

とりあえず同ドメイン名を10.69ドルで購入してJavaScriptを仕込んでみると、見事NoScriptが迂回できた。

しかし何故誰も所有していないドメイン名がホワイトリスト入りされているのか。

どうやら、ユーザーが有名なCDNをホワイトリストに追加するようNoScriptに要請したようだ。

InformAction Forums • View topic - JavaScript CDNs to add to whitelist

NoScript開発者のGiorgio Maoneに、この脆弱性について連絡を撮ったところ、彼の返事と対応は極めて迅速であり、一時間もしないうちに修正パッチがサイト上に上がり、2日後にはアップデートが全NoScriptユーザーに配布されたという。

リンク先の人間は、NoScriptユーザーはホワイトリストを確認し、自分が信頼しないドメインは取り除くべきであると書いている。

2015-06-23

C++標準化委員会の文書 2015-04 pre-Lenexaのレビュー: N4440-N4449

N4440: Feature-testing recommendations for C++

機能テストマクロの提案。C++17機能に対応するマクロが追加されている。

[PDF注意] N4441: SG5: Transactional Memory (TM) Meeting Minutes 2015-03-23 and 2015-04-06

トランザクショナルメモリーの会議の議事録。

N4442: Default argument for second parameter of std::advance (Rev. 1)

std::advanceの第二引数にデフォルト実引数として1を追加する提案。

std::advance( iter, 1 ) ;

のかわりに、

std::advance( iter ) ;

と書ける。

N4443: Introducing alias size_type for type size_t in class std::bitset (Rev. 1 )

std::bitsetにネストされた型名™size_typeを追加する提案。

他のコンテナーとあわせることで、ジェネリックなコードやポータブルなコードを書きやすくなる。

N4444: Linux-Kernel Memory Model

現行のC/C++のメモリーモデルがLinuxカーネル開発者のお気に召さなかった問題を受けて、Linuxカーネルのメモリモデルをまとめた文書。

Linuxカーネルのメモリモデルについて解説した文書。前回のN4374からの変更点はREAD_ONCE()とWRITE_ONCE()マクロの解説。

N4445: Overly attached promise

promiseに共有状態を管理するためのリソースを破棄させるメンバー関数、resetとreleaseの追加。

あるpromiseオブジェクトを使ったとする。

std::future<int> f()
{
    std::promise<int> p ;
    auto future = p.get_future() ;
    p.set_value( 42 ) ;

    // これ以降、promiseは使わない

    // 何らかの時間のかかる処理

    // promiseオブジェクトが破棄される
    return future ;
}

上記の例では、何らかの時間のかかる処理をしているあいだ、promiseオブジェクトは生きている。すると、共有状態を維持するためのリソースも破棄されないまま維持されてしまう。リソースの制約の厳しい環境では、このような不必要なリソースを早期に破棄したい需要がある。

現行規格でも、ムーブを使えばリソースの破棄は可能だ。以下のような方法でpromiseのオブジェクトpをムーブさせてリソースを開放させられる。

p = std::promise<int>{} ; // これでもよい。
std::promise<int>( std::move(p) ) ; // こちらのほうがわかりやすい

しかし、どちらも冗長でわかりにくい。N4445では、promiseから共有状態のリソースを破棄するためのメンバー関数、resetとreleaseを追加する提案をしている。

releaseは共有状態の破棄。resetは空のpromiseとswapをしたかのように働く。

N4446: The missing INVOKE related trait

ある型がある並びの引数の型で関数呼び出しできるかを調べるis_callableの提案。

より厳密に説明すると、N4169で入ったinvokeが未評価オペランドにおいて合法かどうかを確かめる。is_callableの提案。

template <class, class R = void> struct is_callable; // not defined
template <class Fn, class... ArgTypes, class R>
  struct is_callable<Fn(ArgTypes...), R>;

たとえば、is_callable< F ( A0, A1, A2 ) >::valueは、std::invoke< F, A0, A1, A2>が合法の場合にtrueを、substitutionに失敗する場合にfalseを返す。

void f( std::string, std::vector ) ;

constexpr bool b = std::is_callable_v< decltype(&f) ( std::string, std::vector) > ;

[PDF注意] N4447: From a type T, gather members name and type information, via variadic template expansion

「型Tからメンバー名と型情報をVariadic Templates展開で得る」という、なんとも説明的で実用的なタイトルの提案論文。内容として派生的リフレクション機能だ。

その提案内容も極めて実用的だ。typedef<T, C>, typename<T, C>, typeid<T, C>という文法を追加する。Tはクラス型で、Cはコンセプトか型名で、constexpr operator ()でbool値を返す。trueを返したメンバーだけが展開される。

その動作は、サンプルコードを見たほうが良い。


using namespace std;

namespace ns {
    struct X {
        int x, y;
    };
}

vector<std::string> names{ typeid<ns::X, is_member_object_pointer>... };

tuple<typename<ns::X, is_member_object_pointer>...>
    mytuple = make_tuple(typedef<ns::X, is_member_object_pointer>...);

最後の二行のコードは、コンパイラーによって以下のように変換される。

vector<string> names { "x","y" };

tuple<ns::X::int, ns::X::int>
    mytuple = make_tuple(
        &ns::some_struct::x,
        &ns::some_struct::y);

この提案は新しいキーワードを必要としないしASTコントロールも必要としないし特別なコンパイラーマジックやライブラリーも必要としない。

用途は、シリアライゼーション、メタプログラミング、型変換、イベント駆動開発。テスト駆動開発、GUIプロパティエディター、データベースオブジェクトのマッピングインターフェース、ドキュメントの自動化、コンセプトの自動チェック、コンストラクターのリフレクション。

まあ、便利だとは思うのだが、なんとも低級な機能だ。

N4448: Rounding and Overflow in C++

演算の結果の丸めとオーバーフローの挙動を規定できるライブラリの提案。

丸めモードにはすでにfenv.hがあるが、これは不十分だとしている。

丸めモードに対しては、以下の挙動が提案されている。

enum class rounding {
  all_to_neg_inf, all_to_pos_inf,
  all_to_zero, all_away_zero,
  all_to_even, all_to_odd,
  all_fastest, all_smallest,
  all_unspecified,
  tie_to_neg_inf, tie_to_pos_inf,
  tie_to_zero, tie_away_zero,
  tie_to_even, tie_to_odd,
  tie_fastest, tie_smallest,
  tie_unspecified
};

fastestは実行速度優先。smallestは誤差最小優先。

関数には、convertと、divideとrshiftが用意されている。

オーバーフローには、以下の挙動が提案されている。

enum class overflow {
  impossible, undefined, abort, exception,
  special,
  saturate, modulo_shifted, modulo_dividend, modulo_divisor, modulo_positive
};

impossible: オーバーフローは起こりえない。これを指定したプログラムは厳格な検証によりオーバーフローがー起こりえないことを証明すること。

undefined: オーバーフローはまれにしか起こらないので考えなくてよい。

abort: オーバーフローが起きたらabortする。検出が必要。

exception: オーバーフローが起きたら例外を投げる。検出が必要。

special: オーバーフローが起きたら特別な値を返す(IEE浮動小数点数など)

saturate: オーバーフローが起きたら妥当な範囲の値で最も近いものを返す。

オーバーフローを指定できる関数には、convertの他に、limit( lower, upper value )とその派生版と、lshiftが提案されている。

最後に、丸めとオーバーフローを両方取るconvertとbshiftが提案されている。

N4449: Message Digest Library for C++

暗号に使える強度を持ったハッシュ関数ライブラリの提案。

「設計はPythonのhashlibモジュールから恥ずかしげもなくパクった」

まだ文面が不完全だが、Pythonのhashlib風のインターフェースになっている。

ドワンゴ広告

どうやら弊社では、自社から出た最新の参考書を自腹で買う社員が多いようだ。他ならぬKnuth本ならば仕方あるまい。しかし、ご存命のうちに完成するのだろうか。

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

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

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

江添ボドゲ会@7月

江添ボドゲ会@7月 - connpass

7月4日の土曜日に、野方でボードゲーム会を行う。参加費千円。今回はカレー。

7月には引越しを終えて新居でボドゲ会ができるかと見込んでいたのが、どうやらまだ時間がかかりそうなので、今回も野方の妖怪ハウスで行う。

来月こそは引越しをしたい。