2017-11-22

C++標準化委員会の文書: P0770R0-P0779R0

P0770R0:A Proposal to Specify Behavior in Case of Exception Allocation Failure

例外オブジェクトのストレージは未規定の方法で確保されると規格にある。動的確保する実装の場合、確保に失敗した場合に対処する方法がない。

そこで、例外処理が失敗した場合に絶対に失敗せずに投げられる何らかの例外型を追加する提案。bad_allocを再利用するのがよいとしている。

[PDF] P0771R0: std::function move operations should be noexcept

std::functionのムーブ処理をnoexceptにする提案。すでにanyやshared_ptrはnoexceptなのでstd::functionをnoexceptにしない理由はない。

[PDF] P0772R0: Execution-Agent Local Storage

スレッドより軽い実行媒体がTLSを使うとスレッドのTLSが使われてしまう。ExecutorにTLSを要求するAPIを用意して、ExecutorがTLSを提供するか拒否するかして、スレッドより下の軽い実行媒体にもTLSを提供しようという提案。

P0773R0: Towards meaningful fancy pointers

ポインター風に振る舞うクラス型fancy pointerについての考察。ポインターにメタ情報を付加したり、アドレスにnear/far/segmentといった概念があったりする場合に必要。

[PDF] P0774R0: Module Declaration Location

module宣言の文法を変える提案。相変わらず文法が安定しない。

[PDF] P0775R0: Module Partitions

一つのソースファイルに複数のモジュールを書くことができるようにする提案。

P0776R0: Rebase the Parallelism TS onto the C++17 Standard

Parallerism TSはC++14の文面に合わせて書かれていたので、C++17の文面に合わせて書き直す提案。

[PDF] P0777R0: Treating Unnecessary decay

標準ライブラリでdecayを使っているがremove_cvrefですむ場所でremove_cvrefを使うよう書き換える提案。

[PDF] P0778R0: Module Names

モジュールが未だにこんな問題を抱えてるとは、C++20に入るのはおぼつかないのではないだろうか。

モジュールでimport foo ;と書くと、「これはモジュール名fooをimportしろ」という意味だ。ではモジュール名fooに対応するモジュールが定義されているソースファイルは何だろうか。規格は何も定めていない。

ヘッダーファイルでは、ヘッダー名は実装が実ファイルへのマッピングをするヘッダーか、直接物理のファイル名を意味している。ヘッダーを実装しているC++コンパイラーは存在せず、既存のすべてのコンパイラーはヘッダー名をファイル名として解釈し、所定のincludeディレクトリー群からヘッダー名のファイル名を探し出す。

モジュールの実装では、モジュール名、モジュールソースファイル、モジュールバイナリファイルが存在するはずだ。モジュールバイナリファイルは規格の規定するところではないが、モジュールソースファイルを処理した結果の何らかのファイルだ。モジュールの目的がコンパイルの高速化にあるので、当然このような実装になるはずだ。

すると、モジュール名fooをimportしたとき、C++コンパイラーはモジュール名fooに相当するモジュールバイナリファイルを探し出して使う。もしモジュールバイナリファイルがない場合、モジュールソースファイルを探してモジュールバイナリファイルを生成する。要するに今のビルドシステムがやっている依存関係の解決をC++コンパイラーが内部で直接やるようになる。ここでもやはり、モジュール名とモジュールソースファイルのマッピングが必要になる。

このモジュール名とファイル名のマッピングは、現状のままでは実装ごとに異なることになり、ポータビリティのかけらも存在しない使いづらいものになる。

モジュール機能を提供している他のプログラミング言語の例を列挙して比較してみるが、そもそも多くのプログラミング言語は単一の実行環境、単一の実装といったC++とは異なる状況にあるので参考にできないものも多い。

この文書では、モジュール名の文法を識別子から文字列リテラルにしてファイル名とマッピングするルールを追加するように提案している。

[PDF] P0779R0: Proposing operator try() (with added native C++ macro functions!)

なかなか野心的な提案。

expected<T,E>を返す関数が内部でexpected<U,E>を返す関数を呼び、エラーを返した場合はそのエラーを含むoptionalを伝播して返す処理を考える。

template < typename T >
using expected = std::expected<T, std::error_code > ;

expected<int> get_int() noexcept ;

expected<float> get_float() noexcept
{
    auto r = get_int() ;

    // 結果がエラーならば伝播する
    if ( !r )
        return unexpected( r.error() ) ;

    // floatがintを完全に表現できなければエラーを返す
    auto f = float( *r ) ;

    if ( int(f) != *r )
        return unexpected( std::errc::result_out_of_range ) ;
    else
        return f ;
}

このとき、エラーを伝播させるのがとてもだるい。いちいちエラーかどうか調べてエラーならエラーを返す処理を書かなければならない。

このボイラープレートコードを回避するためにCプリプロセッサーマクロを書くのも醜悪だ。

このコードは、コルーチン提案をまねてoperator tryをオーバーロードできるようにすれば解決できる。

template <class T, class E>
constexpr auto operator try(std::expected<T, E> v) noexcept
{
    struct tryer
    {
        std::expected<T,E> v ;

        constexpr bool try_return_immediately() const noexcept { return !v.has_value() ; }
        constexpr bool try_return_value() { return std::move(v).error() ; }
        constexpr try_value() { return std::move(v).value() ; }
    } ;
    return tryer{ std::move(v) } ;
}

これさえあれば、

auto r = get_int() ;
if ( ! r )
    return unexpected( r.error() ) ;
auto i = int(*r) ;

は、以下のように書ける。

int i = try get_int() ;

しかし、operator tryも冗長なコードを大量に書かなければならない。そもそもコルーチン提案自体が冗長なコードを多数書かなければならない。この問題は、ネイティブ言語マクロを導入すれば解決できる。

結局問題は、関数の呼び出し元の文脈でreturnしたいので、Cぷりプロセッサーに変わるネイティブなマクロがあれば、この問題は解決できるし、コルーチンが常用な問題も解決できるし、range-based forも実装できるし、割とあらゆるものがマクロで実装できることになる。

興味深いのはその提案している文法で、文字#を使っている。#はCプリプロセッサーにかけたあとのC++のソースファイルに残らない文字で、既存の実装はプリプロセス後に文字#があるとエラーを吐く。なので安全に機能拡張に使うことができる。

夢が広がる話だ。

ドワンゴ広告

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

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

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

2017-11-21

江添ボドゲ会 11月26日

以下の通り11月26日に自宅でボードゲーム会を開催します。

江添ボドゲ会@11月26日 - connpass

2017-11-20

C++標準化委員会の文書: P0735P0-P0769R0

P0735R0: P0735R0: Interaction of memory_order_consume with release sequences

memory_order_consumeがARMのとても弱いメモリーモデルでは実用的にならないのでなんとかしたいという文書。

P0737R0: P0737r0 : Execution Context of Execution Agents

現在のExecutor提案では実行媒体とかexecutorとか実行リソースについては考慮しているが、具体的なexecution contextについて考慮していない。とりあえず最低限の具体例を定める提案。

P0750R0: p0750r0: Consume

memory_order_consumeは未だにどのC++コンパイラーも実装していない。これは、C++のソースコードレベルでの依存と、ハードウェアでの依存に違いがあるためと、この業界でconsumeという用語の意味が一貫していないためだ。consumeを実装可能にするために色々と提案している文書。

P0752R0: std::vector Destruction Order

vectorの要素の破棄順序を自然にする提案。今まで規格でvectorの要素の破棄順序を規定していなかったので、実装ごとに差異があった。C++では破棄は構築の逆順に行われることが自然なので、vectorも配列やstd::arrayと同じく、末尾の要素から破棄される。

[PDF] P0753R1: Manipulators for C++ Synchronized Buffered Ostream

P0763R0のtypoを修正した。内容は同期バッファーでフラッシュをするかどうかを設定するマニピュレーターの提案

P0756R0: Lambda syntax should be more liberal in what it accepts

lambda-captureの制限緩和の提案。

現在、lambda-captureとして[&x, =]は誤りだ。正しくは[=, &x]。デフォルトキャプチャーの前に個別のキャプチャーを書くことはできない。

現在、lambda-captureとして[=, x]は誤りだ。正しくは[=]。デフォルトキャプチャーと同じ意味の個別のキャプチャーを書くことはできない。

しかし、これの意味は完全に曖昧製無く明らかであるし、初心者がハマる落とし穴であるので、制限緩和すべきであるという提案。

正しい。

P0757R0: regex_iterator should be iterable

filesystemのdirectory_iteratorはrangeとしても使える。

regex_iteratorもrangeとして振る舞うべきだという提案。

確かに、デフォルトコンストラクターが終端イテレーターになるタイプのイテレーターであれば、rangeにもなる。

[PDF] P0761R1: Executors Design Document

実行媒体を表現するExecutorについて。

[PDF] P0762R0: Concerns about expected<T, E> from the Boost.Outcome peer review

Boostのuncheckedの作者からexpectedに物申す文書。どうも些細な違いに思える。

P0766R1: Fixing small-ish functionality gaps in constraints

lambda式でrequires-clauseを使えるようにする提案。

P0767R0: P0767R0: Expunge POD

PODをdeprecated扱いにする提案。これまで規格でPOD型としていた部分はトリビアル型とし、初期化の文脈で「非POD型のグローバルオブジェクト」としていたところは「ユーザー提供コンストラクターで初期化されるグローバルオブジェクト」と書き直す。is_pod traitsはdeprecated扱いになりAnnex Dに移動する。

[PDF] P0768R0: Library Support for the Spaceship (Comparison) Operaton

operator <=>の標準ライブラリによる対応について。

operator <=>はこの前の会議で入ることがほぼ決定した等価比較と大小比較をいっぺんにできる演算子だ。

a == bのとき、a <=> bは0を返す。a < bのとき、a <=> bは<0を返す。a > bのときa <=> bは>0を返す。

また、戻り値は単なる整数型ではなく特別なクラス型で、大小比較できる場合はstd::strong_order, std::weak_order, std::partial_order、等価比較しかできない場合はstd::strong_equality, std::weak_equalityを返す。これらの型は派生関係でis-a関係を表現しているので、例えばstd::strong_orderはstd::weak_orderとしても使えるが逆はない。

大小比較が常にできてa == bのとき、常にf(a) == f(b)が成り立つのがstrong oder、成り立たないのがweak order

例えば文字列のcase insensitiveな比較は等しいと判断されても大文字小文字の違いがあるのでweak_order。

比較ができない値が存在する場合、partial order。

例えばIEEE-754の浮動小数点数はNaN, +0, -0があるのでpartial order。

この文書ではstd::strong_orderなどの標準ライブラリについて細かく定めている。ヘッダーファイルは<cmp>

[PDF] P0769R0: Add shift to <algorithm>

algorithmにshift_leftとshift_rightを追加する提案。

moveとmove_backwardと違い、同じレンジ内で操作する。rotateとは違う。

ドワンゴ広告

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

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

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

glibcのpowがslowpowを呼んで遅い件について

Slow power computation by 64-bit glibc

x86-64 GNU/Linux環境でのglibcのpowは1.0に近い値を渡すと、768bitのソフトウェア実装された浮動小数点数計算を行い高精度な値を得ようとする。slowpowと命名されているこの実行パスは名前通りとても遅い。

glibcはとても基本的なライブラリなので、例えばRubyとかRustのようなプログラミング言語もこの問題に引っかかる。

手元で試したところ、GCC 7.2, glibc 2.26では、-Oと-ffastmathを指定するとpowにslowpowが呼ばれず高速に計算されるようだ。

これでもだいぶ高速化されたのだとか。

Improving math performance in glibc - RHD Blog

2017-11-13

C++標準化委員会の文書: P0650R1-P0722R1

[PDF] P0650R1: C++ Monadic interface

C++でモナドをやるためのライブラリの提案。どうもライブラリでやると煩雑になる気がするのだが。

[PDF] P0655R0: visit<R>: Explicit Return Type for visit

戻り値の型Rを明示的に指定できるvisit<R>の提案。

[PDF] P0657R1: Deprecate Certain Declarations in the Global Namespace

C言語における標準ヘッダーファイル<name.h>はC++では<cname>になった。C++形式のヘッダーファイルをincludeすると、std名前空間スコープに名前が宣言される。同時に、グローバル名前空間に名前が宣言されるかもしれない。

この提案は、C++形式のヘッダーファイルをincludeすると、グローバル名前空間に名前が宣言されることをdeprecated扱いする提案だ。なので、文面は「グローバル名前空間に名前が宣言されるかもしれない」から、「deprecated扱いではあるが、グローバル名前空間に名前が宣言されるかもしれない」になる。

P0658R1: Proposal for adding alias declarations to concepts

conceptのrequires式の本体にエイリアス宣言を書けるようにする提案。

template < typename T>
concept bool SomeReq = requires {
    typename value_type_t<T> ;
    requires Constructible<T, value_type_t<T> > ;
} ;

が、

template < typename T>
concept bool SomeReq = requires {
    using value_type = value_type_t<T> ;
    requires Constructible<T, value_type > ;
} ;

になる。conceptでネストされた型名記述に誤解を生みそうな気がする。conceptはすでにドラフト入りしているのだが、果たして普通のC++プログラマーが書けるようになるのだろうか。

P0670R1: Static reflection of functions

関数呼び出し式から呼び出される関数を得たり引数の型をそれぞれ得たりできるわりと軽めのリフレクション機能の提案。

void func(int);
void func(std::string);
using func_call_m = reflexpr(func(123));
using func_m = get_callable_t<func_call_m>; // reflects void func(int)
using param0_m = get_element_t<0, get_parameters_t<func_m>>;
cout << get_name_v<get_type_t<param0_m>> << '\n'; // prints "int"

[PDF] P0684R1: C++ Stability, Velocity, and Deployment Plans

C++標準化委員会が新機能を追加する際に下位互換性を破壊する変更を伴う時、ユーザーが既存のコードを変更する際に行われる行動を想定した上で、どのようにすべきかという提案。

C++の新しい規格を受容する時は以下のようなステップで行われる。

  1. 新しい規格をサポートした新しいコンパイラーにアップグレードする
  2. 新しいコンパイラーの古い規格モードでの既存のコードをコンパイルすると互換性の問題になる箇所について警告を受ける
  3. 警告を確認してコードを修正する
  4. 新しい規格モードを有効にする

これに従い、下位互換性を破壊する言語機能は容易に警告を出せるかどうかについて注意を払うべきである。

P0692R0: Access Checking on Specializations

知らなかった。

クラスのprivateなメンバーは当然クラス外部からアクセスできないわけだが、既存のほとんどのコンパイラーはテンプレートの明示的特殊化でアクセス指定を無視する。また、GCCとMSVCは部分的特殊化でもアクセス指定を無視する。


class A {
template < typename T >
class impl { } ;
} ;

template < typename T >
struct traits { } 

// 明示的特殊化
// 規格上はエラー
// GCC, Clang, ICC, MSVCは通す
template < >
struct traits< A::impl > { } ;

// 部分的特殊化
// 規格上はエラー
// GCC, MSVCは通す
// Clang, ICCはエラー
template < typename T >
struct traits< A::impl > { } ;

これを踏まえると、現状のC++実装がこの場合にアクセス指定を無視するよう実装していて、またこの仕様ではないとprivateメンバーの型に対する特殊化が出来ないことも考えると、規格を変更してこの制限を取り払ったほうがよいので、明示的特殊化と部分的特殊化ではアクセス指定の制限を緩和をする提案。

P0701R1: p0701r1: Back to the std2::future Part II

名前がよい。

内容はfutureに対する機能追加に対する提案。

[PDF] P0707R2: Metaclasses: Generative C++

現在提案されている静的リフレクションライブラリが入ったという前提でその静的リフレクション機能を使って実装できるmetaclassライブラリの提案。

constexpr {       // コンパイル時実行
    for ( auto m : $T.variables() ) // T型のメンバー変数それぞれに対し
        if ( m.name() == "foo" )  // "foo"という名前のメンバーがあれば
            -> { int bar ; }  // int型の"bar"という名前のメンバーを注入する。

}

割と衝撃的なコードだ。

P0722R1: Efficient sized delete for variable sized classes

sized deallocate functionにクラスへのポインターを取るオーバーロードを追加する提案。

クラスオブジェクトの近隣のストレージ領域を活用した動的にオブジェクトサイズを変えるクラスを実装する時、sizeを効率的に指定するために使える。


void operator delete ( X *, std::destroying_delete_t, その他の引数 ) ;

ドワンゴ広告

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

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

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

今回C++ドラフトに入った機能

Trip report: Fall ISO C++ standards meeting (Albuquerque) | Sutter’s Mill

Herb Sutterが今回の標準化委員会の会議でドラフト入りした機能についていち早く速報を出している。具体的な文書などはリンク先で確認してもらうとして、概要だけ説明する。

range-based forに初期化子が書けるようになった。

for ( auto result = f() ; auto && value : result ) ;

<bit>にbit_castingが追加された。

short from = 42 ;
auto to = bit_cast<std::uint16_t>(from) ;

operator <=>が追加された。

operator <=>は2つのオペランドの大小比較と等号比較を一度にできる演算子だ。この演算子を定義しておけば、残りの比較演算子はコンパイラーが自動的に生成してくれる。型システムによってstrong order, weak order, partial orderのいずれに対応しているかも切り替えられる。

atomic<shared_ptr<T>>が追加された。shared_ptrをアトミックに操作できる。

remove_cvref traitsが追加された。CV修飾子とリファレンスを消したいが、配列から要素型、関数から関数へのポインター型への変換は行いたくない場合に、decayの代わりに使える。

[[nodiscard]]が一部の標準ライブラリで使われることになった。

同期バッファー付きのostreamラッパーライブラリ、osyncstreamが追加。

// 複数のスレッドから同時に実行されうる関数
void f()
{
    std::osyncstream out( std::cout ) ;
    out << "hello, world!\n" ; 
}

スレッドセーフなostreamラッパーとして使うことができる。

<alogorithm>と<utility>の一部をconstexpr対応。

<comlex>をconstexpr対応。

atomic<floating_point_type>

stringとstring_viewにstart_with/end_withの追加。

また、現在策定中のconstexpr対応のnew, vector, stringは、後数回の会議でドラフト入りできる見込みだというぐらい本格的に議論されているようだ。本気で入れる様子が伺える。

ドワンゴ広告

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

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

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

国家政府用のbitcoin破壊工作ガイド

How to Destroy Bitcoin with 51% (pocket guide for governments)

あなた、政府系の人ですか? bitcoin危険だと思いますか? いやいや滅相もない他にやるべきことがたくさんありますよ。まあでも、ちょっとここではbitcoinが疎ましいと思ってくださいよ。そうそう、あなたは中国だとします。

どうやって止めるのですか? みんな暗号通貨はセキュアで無敵だって言うじゃないですか。ちゃんとコントロールしたいあなた達政府系の人にとってはだいぶおつらいですよね。

Bitcoinを止めるのは実際難しくて、個人を何人か逮捕してサーバーを停止させたぐらいじゃ止まりません。Silk RoadやE-GoldやLiberty Reserveとは違うんですよ。そして参加者はだいたい権力を嫌ってます。

暗号通貨では停止させるべき中央サーバーってものがないんですね。ユーザーはみんな、フルノードをセキュリティ目的で実行してますから(理想的な世界ならばそうなのですが、現実ではだいたいのユーザーは有名所のクラウド提供されたWebウォレットを使ってるようですね)

でも、マイナーとかバリデーターとかウィットネスとか呼ばれているルールに従って選ばれた調停者ってのがいます。Bitcoinではマイナーはハッシュ(計算コストが高く安い電気が必要)の発見に精を出しています。そしてほとんどのマイナーはあなたの国にいるんですね。

画像:中国が世界の71%のマイナーを持つ。
https://cdn-images-1.medium.com/max/1600/1*RyaqdlQMBhrdxDlpnCh7eQ.png

マイナーを止めるってのはバカげた話です。Bitcoinはその維持にマイナーを必要となんかしていません。マイナーはセキュリティのために必要なのです。なので、あなたがた政府系の人がマイナーを差し止めたら、難易度調整が入って他の国のマイナー達がネットワークをセキュアにし続けるってわけです。

Bitcoinを殺すなら、ガツンと凶悪な51%攻撃ってやつをやってやりましょう。

ステップ1、bitcoinを買い集める

大手の交換所すべてに、アカウントを作成しましょう。取引所ひとつにつき10から40アカウントぐらい。さて100箇所ぐらいの交換所にそれぞれ40個のアカウントを作りましたね。上出来です。まず景気づけに1億ドル分ぐらいのBitcoinを買いましょう。あなた、政府系の人ですよね? 国家の安全のためにはそれぐらい捻出できますよね?

これを書いている時点でBitcoinの市場総量というのは950億ドルぐらいなので、0.1%ぐらいの量になります。わりかし悪くないレバレッジですね。

交換所にある通貨をすべてあなたの所有するウォレットに送金しましょう。個々が一番難しいところで、暗号通貨のウォレットのユーザーエクスペリエンスは最悪で、誤操作で結構な金を失う可能性があります(ジョークON)

ステップ2,51%のマイナーを見つけましょう

https://www.buybitcoinworldwide.com/mining/china/によれば、世界のマイナーの71%は中国にいます。彼らは地下に隠れていますが、まあでも、そこはあなた中国政府。あなたは人民のスマフォにスパイウェアの導入を義務付けたり、https://thenextweb.com/asia/2017/07/25/chinas-forcing-its-citizens-to-install-a-terrifying-big-brother-app-on-their-phones-or-go-to-jail/しているわけですから、捜索はそう難しくはないでしょう。

ヒント:彼らは盗電してます。調べましょう。

たとえばこれはオルドスの例ですね(北京からそう遠くないですよ)

https://qz.com/1055126/photos-china-has-one-of-worlds-largest-bitcoin-mines/

ステップ3、秘密作戦

さて、秘密警察組織に作戦実行のデイXまでにできるだけ多くのマイナーを捜索するよう命じましょう。

これは法執行機関さんのやることですので、あなたの国のお巡りさんは説得に当たってマイナーの頭に銃を突きつけてもよいでしょう。このお願い方法はマイナーが知らんふりを決め込んでいるのを説得させるのにとても効果的です。

国家政府が物事を成し遂げるってのはこういうことですね。しかも、あなたは中国なのですから、こういう活動をするにあたってリベラルを装う必要すらないのですよ。

ステップ4、倍々ゲーム

マイナー達に以下の操作を行わせましょう。あなたのウォレットの単一のブロックから4000トランザクション(1つあたり25000ドル)ほど掘らせて全体に行き渡らせます。この4000トランザクションはステップ1で作ったアカウント群に送金を戻すことに使います。

通常、取引の成立には6ブロック重ねる(承認)ことが必要です。

さて、世界のネットワークは今や、あなたのブロックの上にブロックを重ねています。その間に、あなたのほったブロックの上に自分でブロックを重ねましょう。

つまり、ブロックNに対してみんなにブロックN+1を送ります。するとみんなBlockN+2とBlockN+3を掘るのに勤しむわけです。あなたはかわりに、別ブランチのブロックN+1BとブロックN+2Bを掘りましょう。

あなたは51%を持っているのですから、たぶんみんなよりは速く掘れるでしょう。よそのマイナー達があなたのブロックに対して6ブロック承認を終えたら、あなたは持っているBitcoinを全部他の何かに交換しましょう。LitecoinだとかRippleだとかEthereumとか、まあ何でもいいです。普通に交換できるはずです。そしたら、あなたは交換したaltcoinをあなたのウォレットに送ります。

BTCをすべてaltcoinに変えて、altcoinを引き出した後に、あなたの4000トランザクションを無効化するもう一つの秘密のブランチを公開します。

これはリオーガニゼーションというやつです。これでネットワークはあなたのチェインを本流として受け入れ、オーファン化した他のトランザクションのことは忘れなければなりません。

ステップ5、暗号通貨市場の価値が暴落するのを眺めましょう

さて、これによって1億ドルの価値があるBitcoin(交換所はもう持っていない)が、1億ドルの価値があるaltcoin(あなたが持っている)に変わったわけです。おめでとうございます。あなたは2億ドル分の暗号通貨を手に入れました。その市場価値は暴落するでしょうが、目的は市場価値の暴落にあるのだから問題ないでしょう。

この攻撃をもう一発行ってもいいのですが、その必要はないでしょう。この規模の攻撃が一度起こっただけでも、暗号通貨に対する信頼に大打撃となり、数年は市場が暴落するでしょう。

よその国家にはどうしようもできません。Bitcoin自体にはまともな法規制や慣習が存在しないのですから。なので秘密に攻撃してもいいし、公に攻撃しても構いません。

再考

この記事は筆者の現状に対する不満を述べたものであるが、筆者はBitcoinに反対するものではない。筆者は我々が現在陥っている愚行について憤っているのだ。

我々はもう一度原点に立ち返ってパラノイアになるべきであり、我々の脅威モデルを適切に設定すべきなのだ。お前が今やっているのは何だ? スマートコントラクト? ブロックチェインによる個人認証? クソコインとクソコインを分散取引? ICO? そういうことは検閲耐性というブロックチェインにおける唯一の重要な事に比べれば完全に無価値なものだ。検閲耐性以外の余りのクソはお前の5ドルのサーバーでも1000倍は効率的にやってくれる。

お前が検閲耐性などいらないのであれば、わざわざビットコインなど使わないでもっと効率的にやれ。

この攻撃はEthereumに対してはより簡単だ(ステップ1,Ethereum創始者のVitalikを捕まえろ)。他の暗号通貨に対しては51%攻撃というのはヘリコプター一台分の金を使ってASICを投下するだけでよい。なのでやるのであれば、Bitcoinに対して攻撃して他の暗号通貨がドミノ効果で信用を失っていくさまを眺めるがよい。

追記:読者が中国ではなく、中国にジェイムズ・ボンド級のスパイを放って51%のマイナーをハイジャック出来ない場合、Bitcoinに対して51%攻撃をしかけるのはもっと難しい。なので中国を説得してやってもらうしかない。

ちなみに、この51%攻撃(Double Spending)は全体の51%のハッシュレートを持っていれば確実に成功するが、51%より少ないハッシュレートしか持たない場合でも、確率的に成功する。この攻撃は一度成功させるだけで信頼に大打撃を与えられるので、全体の20%程度のハッシュレートしか持たず、確率的に数%しか成功しない場合でも、中国共産党が本気で暗号通貨を潰しにかかった場合、割と実現可能性の高い攻撃ではある。

Analysis of hashrate-based double-spending

ドワンゴ広告

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

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

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

2017-11-10

国際標準規格の紹介 〜ISO国際標準規格プログラミング言語C++について〜

はじめに

こんにちは、C++標準会員の江添です。

今日は普段から表に出ている、閉鎖的なゲーム開発では使われていない開発環境についての紹介をします。

今回紹介するのは、ISO国際標準規格プログラミング言語の「C++」です。

なんと表の世界では、国際標準のプログラミング言語は、コンパイラーベンダーやC++利用企業と行ったC++に利害関係を持つ多数の代表が国際標準規格を制定しているのです。当たり前でしょ?

C++は以下のような特徴を持っています。

  • エラーに気づきやすい静的型付け言語
  • C++経験者が理解しやすい言語仕様
  • OSに依存しない移植性の高いC++実装
  • 実行環境に依存しないC++規格準拠の挙動の定義
  • C/C++の関数・クラスに最初からバインドされている

今でもクローズな実装の詳細のわからないプログラミング言語がたくさんあり、それらを使うデメリットは数多くあります。

国際規格の言語を使うのは様々な利点があるからです。

一番大きなものは「権力者の慈悲にすがるしかない状況が発生しない」ことです。もし特定の個人や団体が言語を所有している場合、将来の変更が既存のコードを壊さないこと、自分のほしい新機能が追加されることは、権力者の慈悲にすがるしかありません。ISO傘下の国際規格として制定されることで、企業や個人は等しく最適な言語仕様を考えることができます。

今回はその中の一つとしてCRTPという技法を紹介します。

CRTP

自分の型を返す関数ってよくありますが、面倒くさいですよね。

class A_Class
{
public :
    static auto Create()
    {
        return std::make_unique<A_CLass>() ;
    }
} ;

CRTPを使うと、先程のコードを以下のように書くことができます

template < typename T >
struct factory_mixin
{
    static auto Create()
    {
        return std::make_unique<T>() ;
    }
} ;

class A_Class
    : public factory_mixin<A_Class>
{ } ;

もう少し複雑な例を挙げます。これと似たような(しかもコピーする必要がある)クラスを、名前を変えながら数十、数百と増やしていくことを想像してみてください。

class A_VeryLongClassNameMadeByEzoe
{
public :
    static auto Create()
    {
        return std::make_unique<A_VeryLongClassNameMadeByEzoe>() ;
    }

    static auto CreateWithTwo()
    {
        return std::make_unique<A_VeryLongClassNameMadeByEzoe>(2) ;
    }

    static auto Create( int value )
    {
        return std::make_unique<A_VeryLongClassNameMadeByEzoe>(value) ;
    }

    A_VeryLongClassNameMadeByEzoe() { }
    A_VeryLongClassNameMadeByEzoe( int value )
        : value(value) { }
private :
    int value = 0 ;
} ;

CRTP実装は簡単ですね。

template < typename T >
struct factory_mixin
{
    template < typename ... Types >
    static auto Create( Types && ... args )
    {
        return std::make_unique<T>( std::forward<Types>(args)...) ;
    }

    static auto CreateWithTwo( )
    {
        // T::T(int)を持たない型は除外
        constexpr bool b = requires { T(2) ; } ;
        static_assert( b, "Type doesn't have constrcutor T::T(int)." ) ;
        if constexpr ( b )
        {
            return Create(2) ;
        }
    }
} ;

CRTPがあるとゲームでよく使われる状態遷移モデルのような仕組みを描くのが大変楽になります。

現場では以下のようなクラスがたくさん作られるため、面倒なコードの重複によるバグを減らす(これが大切)ことができるのです。


template < typename T >
struct change_state_mixin
{
    static void ChangeState( Obj aObj )
    {
        T newState( aObj )
        aObj.stateChanger().setNextStage(newState) ;
    }
} ;

// 待機状態
struct StateWait
    : change_state_mixin<StateWait>
{
    void procAnim()
    {
        // 状態ごとに違う処理
    }
}

// プログラマーにコピペを強いる状態
struct StateForceHallabProgrammerToCopyPasteTheBoilarPlateCode
    : change_state_mixin<StateForceHallabProgrammerToCopyPasteTheBoilarPlateCode>
{

    void procAnim()
    {
        // コピペ処理
        yank() ;
        jjjjjjjjjjjjjjjjjjjjjjj() ;
        paste() ;
        enter_insert_mode() ;
    }
}

まとめ

わざわざ閉鎖的な環境で独自言語を開発しなくても、ライブラリ作者向けの強力な機能が提供されているのがC++の強みです。時代とともに変化する様々な環境にも、C++は対応し続けています。

これ以外にも、C++ではボイラープレートコードを削減するために様々な機能がありますが、それはまたの機会にぜひ。

国際標準規格C++は、C++に利害関係を持つ様々な個人や企業がC++標準化委員会に代表を送り、ISOのルールに則って新機能の考案や策定を進めています。もし現行のC++に不満があるのであれば、C++標準化委員会に代表を送って提案し、実験的実装をし、その価値を示し、国際会議で議論して、規格策定に貢献しましょう。

真面目なまとめ

元ネタは以下の通り。

社内開発環境の紹介 ~社内製プログラミング言語Mintについて~ | ハル研ブログ | ハル研究所

元ネタで対処しようとしている問題は、コードをコピペするから生じるのであって、コードをコピペしなければよい。コードの重複を防ぐためには、昔から基本クラスという便利な機能がある。これにC++のテンプレートを組み合わせればボイラープレートコードをコピペして一部変更という不毛な処理を人間がする必要はない。そして、コンパイル時に解決できる問題はコンパイル時メタプログラミングで解決できる。

そして、C++の言語機能に不満があるのであればC++標準化委員会に出てきて議論するべきだ。例えばC++17にはメモリ解放処理で何もしない、単なるポインターを加算して返すだけのメモリ確保ライブラリのモノトニックバッファーリソースが入った。C++20には、ソート済みの連続したストレージで実装された連想コンテナーのflat_map/flat_setや、歯抜けを許す連続したストレージで実装したvectorのようだが中間要素の削除が早いcolonyなど、コルーチン、スタックフルコンテキストスイッチライブラリなど、ゲーム用途にも便利な新機能がたくさん提案されている。他にも、this_typeで解決したい問題にも適用できる、静的リフレクション機能も活発に議論されている。C++を活用するのであればC++に貢献すべきだ。

2017-11-08

C++標準化委員会の文書: P0586R0-P0649R0

P0586R0: Safe integral comparisons

2つの整数型の値を安全に比較するためのライブラリの提案。

2つの異なる整数型の値を比較する時、符号が違ったり、一方がもう一方の表現できる範囲ではない場合、人間にとって不自然な結果になる。安全に比較するためには様々な符号や暗黙の型変換の考慮が必要だが、それを正しく書くのは面倒だ。なので標準ライブラリがほしい。

P0593R1: p0593r1: Implicit creation of objects for low-level object manipulation

以下の現行規格では未定義の挙動となるコードの挙動を規格で定義する提案。

struct X { int x ; } ;

int main()
{
    X * p = (X *) malloc( sizeof(X) ) ;

    p->x = 0 ; // 未定義の挙動

    free( p ) ;
}

このようなコードはC言語ではよく書かれるが、C++では未定義だ。構築されていないオブジェクトへのアクセスは未定義の挙動だ。このコードはオブジェクトを構築していない。したがって挙動は未定義だ。

しかし、現実を見ると、プログラマーはこのコードが動くことを期待しているし、現実のC++コンパイラーはこのコードの挙動について一致している。規格は現実を追認すべきだ。

すると、どのような型ならば制限を緩和するかということになるが、構築や破棄にあたってコードが実行されない型ならばよい。これには、スカラー型、配列型、トリビアルなコンストラクターとデストラクターを持つクラス型が当てはまる。

[PDF] P0609R1: Attributes for Structured Bindings

構造化束縛に属性を記述できる文法を追加する提案。

auto [a, b [[attribute]], c ] = e ;

[PDF] P0624R1: Default constructible stateless lambdas

stateless lambdaによって生成されるクロージャーオブジェクトをデフォルト構築可能にする提案。

auto f = (){} ;
decltype(f) g ; // OK
g() ; // OK

stateless lambdaならばクロージャーオブジェクトをデフォルト構築しても問題になることはない。クロージャーオブジェクトがデフォルト構築可能になることで、より汎用的に関数オブジェクトとして使いまわせる。

[PDF] P0631R1: Math Constants

数学定数を追加する提案。

ヘッダーファイルは既存のヘッダーファイルに追加するのであれば<cmath>か<numeric>、新しいヘッダーファイルにするのであれば<math_constants>が提案されている。

さて、数学定数はstd名前空間スコープの下に宣言されるわけだが、これは問題がある。というのも数学定数にはeといった小文字一文字の名前もあるので、以下のようなコードは壊れる。

using namespace std ;
int e ;

これは自業自得と言えば自業自得だが、とはいえ小文字一文字という名前はstd名前空間下であっても危険すぎる。

そのため、e_vのような形にするか、あるいはstd::math_constants下に置くという提案がされている。

提案では数学定数は変数テンプレートの形を取る。

template < typename T > inline constexpr T e ;

これにより任意の型に対応できる。

P0634R1: Down with typename!

依存名が型を意味するときにはtypenameを書かなければならないが、文脈上型しか書けない場所には書かなくてもすむようにする提案。

template < typename T >
auto f( T::type ) -> T::type
{
    using t = T::type ;
    new T::type ;
    static_cast<T::type *>(nullptr) ;
}

template < typename T >
struct A : T::type
{
    T::type t ;
} ;

現在の標準規格では以下のように書かなければならない。


template < typename T >
auto f( typename T::type ) -> typename T::type
{
    using t = typename T::type ;
    new typename T::type ;
    static_cast<typename T::type *>(nullptr) ;
}

template < typename T >
struct A : T::type
{
    typename T::type t ;
} ;

大変だ。

P0636R2: Changes between C++14 and C++17

C++14からC++17の間の変更点。

[PDF] P0642R1: Structural Support for C++ Concurrency

構造化プログラミングがループをパターン化して簡単に書けるようにしたように、並列処理をパターン化して簡単に書けるようにした並列処理に対する構造化サポートのためのライブラリの提案。

P0644R1: Forward without forward

forwardを書かずにforwardする提案。

Perfect Forwardingはだるい。例えば関数オブジェクトFuncに引数Argsを渡して戻り値を返す転送関数をPerfect Forwardingで書く場合

template < typename Func, typename ... Args >
decltype(auto) f( Func && func, Args && ... args )
{
    return std::forward<Func>(func)( std::forward<Args>(args)... ) ;
}

これをラムダ式で書く場合

auto f = []( auto && func, auto && ... args ) -> decltype(auto)
{
    return std::forward<decltype(func)>(func)( std::forward<decltype(args)>(args)... ) ;
}

とてもだるい。

そこで、この提案ではオーバーロード不可能な単項operator >>を追加することにより、適切なforwardingを行う昨日を提案する。

template < typename Func, typename ... Args >
decltype(auto) f( Func && func, Args && ... args )
{
    return (>>func)( >>args... ) ;
}

auto g = []( auto && func, auto && ... args ) -> decltype(auto)
{
    return (>>func)( >>args... ) ;
}

だいぶ楽になった。

[PDF] P0649R0: Other Product-Type algorithms

構造化束縛で分解できる型をproduct typeと呼び、その分解して得られる値を得るためのライブラリがP0327R2で提案されている。この提案は、product typeに対するtuple風アルゴリズムの提供だ。

たとえばfor_each

int main()
{
    std::tuple t(1, 3.14, "hello") ;

    std::product_type::for_each( [](auto x){ std::cout << x << '\n' ; }, t ) ;
}

構造化束縛できるあらゆるproduct typeに使えるfor_eachだ。他にも様々なアルゴリズムが提案されている。Boost.FusionやBoost.Hanaからアイディアを得ている。

ドワンゴ広告

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

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

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

2017-11-06

C++標準化委員会の文書: P0533R1-P0573r2

[PDF] P0533R1: constexpr for <cmath> and <cstdlib>

algorithmをconstexpr化する提案で分離されたcmathとcstdlibのconstexpr化についての提案。組版がクソで読む気がしないが、一般的な算術演算子だけで実装できるものはconstexpr化できる。errnoの書き換えはconstexprではできないが、constexprの文脈で評価されたときの挙動を規定すればconstexpr化できる。

[PDF] P0534R3:call/cc (call-with-current-continuation): A low-level API for stackful context switching

いわゆるcallccを実現するためのスタックフルなコンテキストスイッチを実現するための低級ライブラリの提案。コルーチン提案よりよっぽどわかりやすいのでこっちのほうがいい。

P0539R2: A Proposal to add wide_int Class

Nビットの整数型を表現するwide_int<N>の提案。

より大きな整数型の需要は年々高まるばかりで、GCCとClangには__int128型が存在する。将来的には256bitなどのより大きな整数型が出てくることは想像にかたくない。そこで、大きなサイズの整数型を汎用的に表現する方法がほしい。

この提案では2の乗数の整数型しか扱わないが、将来的には拡張できる余地を残す。

P0546R1: P0546r1 : Span - foundation for the future

配列に範囲外チェックを行いつつアクセスできるストレージを所有しないライブラリspanの提案。

[PDF] P0549R2: Adjuncts to std::hash

ある型Tが有効なstd::hash<T>を持つかどうか調べるis_enabled_hash<T>、CVリファレンス修飾子を取り除いた型が有効なハッシュを持つかどうか調べるhash_for<T>、そしてハッシュ値を得るhash_value<T>(T && t)、ハッシュが例外を投げないか返すis_nothrow_hashable<T>の提案。

[PDF] P0551R1: Thou Shalt Not Specialize std Function Templates!

標準ライブラリの関数テンプレートはユーザーが特殊化してはならないというルールの追加。なぜならば、ろくな結果にならないから。

P0561R2: An RAII Interface for Deferred Reclamation

リーダーライターロックのパターン、つまりあるオブジェクトの値を読むリーダーがリーダーロックをして値を読む。アップデーターは新しいメモリを確保して差し替えることで値を更新する。リーダーロックはアップデーターを妨げない。メモリの解放は最後のリーダーロックが外れて問題ないときに行う。

このようなパターンを実現する方法として、リファレンスカウント、RCU、ハザードポインターといった方法が考案されていて、実際標準ライブラリに入れるべく提案もされている。問題は、提案は個別の実装方法に特有の低級な操作を提供している。本提案は、このパターンを実現する実装方法によらない汎用的な高級APIを提案する。

たしかにほしい。

[PDF] P0566R3: Proposed Wording for Concurrent Data Structures: Hazard Pointer and Read-Copy-Update (RCU)

ハザードポインターとRCUの文面案。もともと別の提案だったが似通った機能を提供するため、文面案を一緒にすることにしたとのこと。

P0571R1: p0571r1: Type Requirements for <numeric> Algorithms

<numeric>の一部のアルゴリズムに型要件が曖昧な部分があったので修正する。例えばaccumulateなどのアルゴリズムで、内部で使われる一時オブジェクトの型がどうなるか曖昧で実装の差異が生じていた。

P0573R2: Abbreviated Lambdas for Fun and Profit

省略ラムダの提案。

ラムダ式の本体として=> 式と書けるようになる。=>の場合、戻り値の型推定は-> decltype(auto)扱いになり、 例外指定もnoexcept(式)扱いになる。=>の場合、引数の型を省略できる。その場合auto &&と書いた扱いになる。


std::sort( b, e, [](a,b) => a < b ) ;

このコードは、


std::sort( b, e, []( auto && a, auto && b ) noexcept(a < b) -> decltype(auto){ return a < b ; } ) ;

と書いたものと同じ意味になる。

ほしい。

ドワンゴ広告

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

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

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

2017-11-05

VimConf 2017に行ってきた

以下で告知されているVimConf 2017に行ってきた。

vim-jp » VimConf 2017を開催します

私はVimを毎日使っているし、実際このブログ記事もNeovimで書いているが、肝心のVim力はさほど高くない。私はHJKLではなくArrow Keyを使うし、マウスも使う。大抵のテキスト編集作業はInsert Modeで行う。ノーマルモードで行う作業はペースト(これも面倒なのでInsert Mode内でCtrl+Rを使うこともしばしばあるのだが)やgJ、数行の自作の関数によるHTMLでエスケープが必要な文字のエスケープとか、ブログ記事をBloggerで公開するときに本文やタイトルをコピーしたり、Bloggerへのリンクを挿入したりする作業だ。その他には:makeも使っているが、これは別にVimとはあまり関係がない。人から「でもあなたはoを使っているでしょう。他のエディターにはなかなか見かけない便利な機能です」と言われたことはあるし、実際oは使っているが、oはVimがモードを持つから存在するだけで、モードを持たないテキストエディターならばoはいらないのではないかと思う。

そんな私がなぜVimConf 2017に行ってきたかというと、たまたま私が雇用されている会社、ドワンゴがVimConf 2017のスポンサーになっていたため、スポンサー枠がひとつ余っていたのだ。

さて、会場の空気はと言うと、だいぶ常人離れしていて、毎朝Vimをビルドするのは当たり前という人がゴロゴロいた。

発表者と発表に使ったスライド資料の一覧を記したタイムテーブルがどこかにあればいいのだが、そういう便利なものが見当たらないので、仕方なく記憶を頼りに書く。

haya14busaの自分のVimに関する活動史についての発表、これは特に大した印象が残らなかった。

fatihのvim-goの発表。vim-goとはvimをgo開発環境にするプラグインだ。その機能はgoの実装をインストールする機能に始まり、テストでcoverageされた部分のコードをハイライトする機能まであり、なかなか良さそうだ。

デバッガーのサポートは現状のvimでは難しいが、LSPへの対応により状況は変わるだろうとの期待がある。

VimConf 2017では昼になかなか豪華なすき焼き弁当がでた。壇上にmattnとk_tanakaとkaoriyaが上がって弁当を食べるところを眺めながら弁当を食べた。

昼の休憩の間に色々と参加者に対する質問が行われたが、Microsoft Windowsを使っている参加者は数えるほどしかいなかった。WindowsdもMacOSdもGNU/LinuxでもないOSを使っているものはいるのだろうかと思ったが、Chrome OSを使っている者がいた。少し期待していた答えとは違う。Wayland上でvimを使っているのは、私ともうひとりしかいなかった。ただ、私ももうひとりも、Waylandは使っているものの、vim自体は端末エミュレーター上で動かしているため、果たしてそれはWaylandで使っていると言えるのか疑問だ。

cocoponのcolor schemeを作成する発表。color schemeを作るための割と全てが解説されていた。どうやらcocoponによると、我々プログラマーは一日のうち8時間は眠り、8時間を日常の雑事や余暇に使い、8時間は働いている。すなわち、我々は一日のうち8/24にあたる33%の時間はcolor schemeを見ていることになる。したがってcolor schemeは極めて重要だ。通勤途中に急にcolor schemeを眺めたくなることがあるらしいので、Vimのcolor schemeを比較できるWebサイトを作り、モバイル対応もさせているらしい。

t9mdによるAtomでVim風の操作を実現するVMPの発表。Vimの操作はテキストバッファーに対する変更であり、その文法はoperator + targetであるといったVim操作の本質の話、後半ではVim操作のデモ(Atomで動くVMPによるデモ)が行われた。

私はVimでtext objectというものは使っていなかったのだが、熟練のvimmerはyipとvipが息を吐くように行えるのだという。AtomのVMPではtext objectを入力すると対応する部分がフラッシュするようになっていて、UIフィードバックがあるので、操作しやすくなっている。これはVimにも欲しいところだが、AtomはElectronで実装されていれるがためにCSSを数行書くだけでできる実装が、Vimでは難しいとのことであった。

text objectは覚えたいところだ。

senopenはPOSIX原理主義者として移植性の高い.vimrcの記述方法についての発表。移植性の高い.vimrc、つまりどんな環境に持っていっても変更無く正しく動作する.vimrcはどう書けばいいのか。まず、現実の環境で対応しなければならないVimのバージョンの下限を調べる。どうやらある有名なクラウドサーバーではCentOS 5.5をサポートしているらしく、するとVim 7.0を下限とすればよい。また、WindowsとPOSIXではファイルパスのフォーマットが違う。文字コードが違うといった問題があり、これに正しく対応するための記述方法が示された。

暗黒美夢王ことShougoMatsuは暗黒の力によって作られているスニペットプラグインの発表。スニペットプラグインとは何か。スニペットプラグインの実装方法とその長短について。新しいdeoppet.nvimではVimにスニペットプラグインを作りやすくするための機能を追加することにより、パフォーマンスの問題を解決したなどと話していた。今回は歌はなかった。

dice_zuは、ordinaryな人間がVimに貢献する方法について発表。どうやら彼の定義するところのordinaryには、毎朝Vimをビルドすることが含まれるらしい。

p_ckはVimのシンタックスハイライトを記述する新しい方法について発表。既存のシンタックスハイライトの記述方法がいかにダメかという話をしていた。

lambdalisueはgitのVimフロントエンドであるgina.vimについて発表。この発表を聞いた我々は、スーパーVimマン2になれるそうだ。スーパーVimマン2とは、CLIツールをVimで代替するスーパーVimマンを超えた人のことだそうだ。ちなみに、スーパーVimマン2を超えたスーパーVimマン3が存在し、これはデスクトップアプリをVimで代替する超人のことだそうだ。肝心のgina.vimだが、git logをVimで表示することができ、かつコミットを選択するとその変更内容を別枠で表示するなどの機能があり、たしかに便利そうだとは思った。しかし私はgitにVimフロントエンドが必要だとは思わない。

VimConf 2017は国際カンファレンスという位置づけであり、発表の半分以上は英語で行われ、英語と日本語の同時通訳がついていた。私は英語は英語として聞いていたので日本語通訳は聞いていなかったのだが、どうも日本語通訳はだいぶ独創的な翻訳でなかなか面白かったらしい。何でもアレがソレしてヤバイとか。

VimConfの規模をもっと大きくして来年も行うために、スポンサーを募集しているそうだ。

2017-11-01

C++標準化委員会の文書: P0399R0-P0515R2

[PDF] P0399R0: Networking TS & Threadpools

ネットワークライブラリーはスレッドプールを使いたいがどのようになるのかということを大雑把に説明したスライド資料。

[PDF] P0424R1:Reconsidering literal operator templates for strings

文字列リテラルに対するユーザー定義演算子で文字列を(harT const *, std::size_t)で取れるようにする提案。

template < typename CharT, CharT const * str, std::size_t length >
auto operator "" _udl() ;

auto x = "abcd"_udl ;

[PDF] P0429R2:A Standard flat_map

ソート済みの連続したストレージで実装されるset/mapの実装。flat_set/flat_mapの提案。

既存のset/mapはノードベースのバイナリーツリーによる実装で、これは現代のメモリが凄まじく遅くキャッシュミスが悲惨なことになるアーキテクチャではとても遅い。連続したストレージはキャッシュが聞きやすく、キャッシュが聞いたメモリ領域への読み書きは高速に行える。すると、ソート済みの配列をバイナリサーチする実装のほうが、現実のアーキテクチャでは速度の点で有利だ。

入ってほしい。

P0443R3:A Unified Executors Proposal for C++

実行媒体を表現するexecutorライブラリの提案

P0447R4: Introduction of std::colony to the standard library

歯抜けを許す連続したストレージ上に構築される要素の順序保証のないコンテナー、colonyの提案。

vectorのような連続したストレージ上に構築される要素の順序保証のあるコンテナーを考える。

std::vector v = {1,2,3,4,5} ;
// 中間の要素を削除
v.erase( v.begin()+2 ) ;

このコードは遅い。なぜかというと要素3を削除したあとに、要素3が構築されていたメモリー上に要素4をコピーし、要素4の場所には要素5をコピーして、間を詰めなければならないからだ。vectorでは最後尾以外の要素の削除は遅い。

では要素を詰めなければいいのではないか。eraseを行った後のコンテナーの中身が、{1,2,無効,4,5}となるデータ構造はどうだろうか。要素にアクセスする際は無効になった要素を読み飛ばして無視する。要素2と4の間に要素を挿入すると、無効化されていたストレージに要素が追加される。さらに、位置を指定せずに挿入すると、無効化されているストレージのどこかに要素が追加される。

colonyは要素の順序を保証しないが、中間の要素が定数時間で行える特性を持つコンテナーだ。

なお、リファレンス実装では、無効要素の読み飛ばしは要素ごとに無効フラグを持つのでもなく、ビットマップで無効フラグを持つのでもなく、jump-counting skipfieldと呼ばれる手法を用いるらしい。これによって連続した無効要素を読み飛ばすのがキャッシュ効率よく行えるそうだ。

The Advanced “Jump-Counting” Skipfield Pattern

[PDF] P0461R2: Proposed RCU C++ API

同期処理のためのRCUライブラリの提案。

P0479R2: Attributes for Likely and Unlikely Statements

起こりうる可能性の高さと低さを指定する属性、[[likely]]と[[unlikely]]の提案。

例えば分岐時に実行される可能性の低いブランチに指定することで、コンパイラーの最適化を助けることができる。


if ( is_error )
[[ unlikely]] {
// めったに起こらないエラー
}

GCCとClangは独自拡張として__builtin_expectという同等機能のcompiler intrinsicsを提供している。MozillaやChromiumのような現実のコードでも使用されている。

現実にどのように活用されるかというと、例えばキャッシュを多用するアーキテクチャでは、コードブロックの配置の場所によってキャッシュされるかどうかが変わるので、分岐時により実行される可能性の高いコードをキャッシュされやすい領域に配置することができる。x86では、隣接する複数の命令は内部で単一の命令にまとめられたりするので都合が良い。

[PDF] P0506R2: use string_view for library function parameters instead of const string & / const char *

string_viewを標準ライブラリで文字列を受け取る引数の型として積極的に使っていこうという提案。std::string const &やchar const *で受け取るよりよい。

[PDF] P0514R2:Efficient waiting for concurrent programs

スレッド所有がないmutexとして、atomic_semaphoreの提案。atomic操作にatomic_waitやatomic_notify_oneも追加。そしてcondition_variable_atomicも提案。

[PDF] P0515R2:Consistent comparison

C++における比較をより厳密にするための新しい演算子、operator <=>の提案。

operator <=>(a, b)はa, bの大小関係と等号関係に応じて適切な3値のいずれかを返す。また、strong order, weak order, partial order, strong equality, weak equalityも型で表現する。

これでだいぶ比較がマシになる。今まで同じ演算子にごちゃまぜにしすぎていた。

ドワンゴ広告

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

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

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

2017-10-30

C++標準化委員会の文書: P0260R2-P0356R2

P0260R2: C++ Concurrent Queues

名前通り、競合なく複数のスレッドからアクセスできるconcurrent queueの提案。ヘッダーファイルは<conqueue>、キュー本体の名前はbuffer_queue。

P0275R2: A Proposal to add Classes and Functions Required for Dynamic Library Load

C++にshared library(WindowsではDLLと呼ばれている)機能を追加する提案。

shared library機能は広く使われているが、現在C++規格はshared libraryを直接サポートしていない。


// libearth.soという名前のshared libraryファイルを読み込む
shared_library lib("libearth.so") ;
// シグネチャがint(std::string)でシンボル名がquestionの関数へのポインターをlibearth.soから得る
auto ptr = lib.get_if<int (std::string)>("question") ;

int result = ptr("the answer to life the universe and everything"s) ;

[PDF] P0303R0: Extensions to C++ for Short Float Type

floatより小さいshort floatの提案。

short float x = 1.0sf ;

規格はshort floatのサイズとフォーマットを規定していないが、背景にはIEEE 754-2008のhalf precision floating pointであるbinary16を念頭に置いている。

[PDF] P0315R3: Lambdas in unevaluated context

lambda式を未評価式の中でも使えるように制限緩和する提案。ただし、外部リンケージを持つ関数のシグネチャーにlambda式が含まれないように注意深く制限はする。

[PDF] P0323R3: Utility class to represent expected object

expected<T,E>の提案。このクラステンプレートはT型の値を保持することが期待されているが、T型の値を保持できないときには、期待通りではないエラーの意味を示すためにE型の値を保持する。

ある型の値を用意できないときに、値を保持していないことを示すためには、optional<T>が使えるが、エラーの詳細な情報を伝えたいときには、エラー通知用の型の値を渡したい。そのために、ここで提案しているある型かエラー型の値を保持するexpectedが使える。

[PDF] P0327R3:Product types access

構造化束縛で分解できる型をすべて分解することができる機能の提案。ようするにジェネリックなtuple_size/tuple_element/getの提案だ。

コア言語でやる場合、size/element/getの機能を提供する演算子を提供することになるが、キーワードの追加が必要になる。そしてtraitsでカスタマイゼーションポイントを提供しているライブラリでは使えない。

ライブラリでやる場合、現状のコア言語仕様ではビットフィールドに対応できない。

これは必要だ。

[PDF] P0330R1:User-Defined Literals for size_t

std::size_tに対するユーザー定義リテラル。zu。

#include <cstddef>
using namespace std::support_literals ;

// std::size_t
auto x = 0zu ;

これはほしい。std::support_literalsではなく、すべての標準ライブラリのユーザー定義リテラルを使えるようになるstd::literalsでもよい。

P0332R1: P0332r1 : Relaxed Incomplete Multidimensional Array Type Declaration

mdspan(多次元配列スパン)のために不完全配列の宣言の文法の制限を緩和する提案。添字数を一切書かなくてよくなるので、int[][][]などと書けるようになる。

これにより、以下のようにmdspanが書けるようになる。

// 現在提案中のmdspanの宣言
// 3次元テンソル型
using tensor = std::mdspan<double,std::extents<std::dynamic_extent,std::dynamic_extent,std::dynamic_extent>> ;

// この提案が入れば書けるようになる上と同等の宣言
using tensor = std::mdspan<double[][][]> ;

楽になる。

しかし、連続したストレージを所有しない多次元配列に見せかけるラッパークラスとして、mdspanという名前は本当に通じるのだろうか。これはもともとarray_viewと呼ばれていたが、viewという用語は正しくないと物言いがついたために、spanになった。mdspanとは、Multi-Dimentional spanだ。果たして日本語でスパンといって伝わるのだろうか。

ただ、考えてみれば、ラッパーとかサンクといった用語も当初は日本人に馴染みのない用語だったはずで、イテレーターやデリゲートやクロージャーといった用語も最初は聞き慣れない用語だったはずだ。かつてはアドレスを番地と言ったものだ。

P0355R4: Extending <chrono> to Calendars and Time Zones

chronoをカレンダーとタイムゾーンに対応させる提案。これでようやくC++で日付処理が可能になる。

P0356R2: Simplified partial function application

std::bindにかわる新しいbind_frontの提案。この提案ではstd::bindのdeprecated化を提案している。

引数を5個とる関数fが以下のようにあるとして、

int f( int, int, int, int, int ) ;

これの第一引数だけ指定して残りを受け取る引数4個の関数を作り出す場合、std::bindでは以下のように書く。

bind( &f, 42, _1, _2, _3. _4 ) ;

わりとだるい。そもそも実引数の数を把握してそのとおりに書くのがとてもだるい。

lambda式ならどうか。

[]( auto && ... args ) { return f( 42, std::forward<decltype(args)>(args)... ) ; } ;

割と難しい。このようにC++14のlambda式を使いこなし、かつPerfect Forwardingも完璧にスラスラと書けるようになる頃には、京都で9年ぐらいニートした挙句にC++の参考書を出版するようになっているか、岡山で陶芸でもしている。

bind_frontは先頭の引数だけを指定することに特化したライブラリだ。以下のように書ける。

bind_front( &f, 42 ) ;

まあ、わかりやすいとは思うが、そう都合よく先頭だけ引数を指定したい場合があるだろうか。

ドワンゴ広告

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

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

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

2017-10-27

C++標準化委員会の文書: P0009R4-P0237R9

2017年10月分の文書が公開された。この8ヶ月ほど、C++17参考書の執筆に注力していて文書のレビューを怠っていたが、さっくりと解説して、次はC++入門書の執筆に移りたい。

P0009R4: P0009r4 : Polymorphic Multidimensional Array Reference

改定に改定を重ねてわけのわからないことになっている連続したストレージに対して多次元配列風のアクセスを提供するラッパーライブラリ。もともとarray_viewだったが、今ではmdspanという一見してわけのわからない名前になっている。これは、viewという用語が適切ではないという違憲によって変更された。

もともとレイアウト指定はなかったのだが、レイアウト指定は絶対に必要だという違憲があって追加された。C/C++風の末尾の次元がメモリ上で連続しているレイアウトと、FORTAN風の先頭の次元がメモリ上で連続しているレイアウト、そして、subspanで一部を切り出したときにメモリが連続していないことを示すレイアウトがある。

割と一見してコードの意味がわからなくなりそうな設計をしている。

P0037R4: Fixed-Point Real Numbers

markdownで書かれている。ほー、いいじゃないか。こういうのでいいんだよ。こういうので。焦るんじゃない。俺はPDFで読みたくないだけなんだ。

固定少数点数ライブラリfixed_point< Rep, Exponent>の提案。

fixed_point< uin32_t, -12 > a(1), b(2) ;

// 0.5
auto c = a / b ;

fixed_point<Rep, Exponent>の指数はpow(2, Exponent)となる。最小値はnumeric_limits<Rep>::min() * pow(2, Exponent)、最大値はnumeric_limits<Rep>::max() * pow(2, Exponent)

面白いことに、クラステンプレートのコンストラクターからの実引数推定と実引数推定ガイドを使った、初期化子の整数値からのExponentの推定機能がある。

auto a = fixed_point(0ul);
static_assert(is_same_v<decltype(a), fixed_point<unsigned long, 0>>);

Exponentは初期化子の整数値を表現できる最大の値が選ばれる。

また面白いことに、演算結果でRepやExponentが変わる。operator *ではRepが変わらないが、multiply/divideではRepも変わる。


// 安全に演算結果を表現できる型に変わる。
auto f = fixed_point<uint8_t, -4>{15.9375};
auto p = multiply(f, f);
// p === fixed_point<uint16_t, -8>{254.00390625}

// operator *だとRepが変わらない。
auto f = fixed_point<unsigned, -28>{15.9375};
auto p = f * f;
// p === fixed_point<unsigned, -56>{0}

// Repも変える
auto f = fixed_point<unsigned, -28>{15.9375};
auto p = multiply(f, f);
// p === fixed_point<uint64_t, -56>{254.00390625}

これは除算の場合も同じだ。


fixed_point< uint32_t, -16> a(1), b(2) ;
auto c = a / b ;
// c == fixed_point< uint32_t, 0>(0)

auto d = divide( a, b ) ;
// d == fixed_point<uint64_t, -32>(0.5) ;

Exponentの変化は、乗算の場合それぞれのExponentの加算、除算の場合は減算になる。

わかりやすいようなわかりにくいような。最悪の場合を想定しすぎなような。

exponentが小さくてもすむ型であれば最初から小さくしとけというのはわかるが、あまりにも目まぐるしくExponentが変わりすぎる。文書は組み込み型のDrop-in Replacementを意図して設計されているというが、以下の関数テンプレートに渡してエラーになるようなライブラリが本当にdrop-in replacementたりえるだろうか。

// 値を半分にして返す関数
template < typename T >
T half( T x )
{
    return x / T(2) ;
}

このコードは、どんなfixed_pointを渡しても、小数部が切り捨てられる。

P0096R5: Feature-testing recommendations for C++

機能テストマクロがC++17に対応。

P0124R4: Linux-Kernel Memory Model

Linuxカーネルのメモリーモデルの解説。

[PDF] P0196R4: Generic none() factories for Nullable types

ポインター、optionalなどnullableな型に使えるジェネリックなnone()の提案。

[PDF] P0201R2:A polymorphic value-type for C++

polymorphic_value<T>の提案。コピー時にT型を基本クラスとするpolymorphic typeをディープコピーしてくれるクラス。ディープコピーをするためにT型は何か特別なclone関数を用意する必要はない。


struct Base { int x ; } ;
struct Derived : Base { int y ; } ;

polymorphic_value p1( new Derived ) ;

// 値がディープコピーされる
polymorphic_value p2 = p1 ;
// Derivedのデストラクターが呼ばれる

アロケーターの指定がないのはなぜだろう。

P0202R2: A Proposal to Add Constexpr Modifiers to Functions in <algorithm> and <utility> Headers

algorithmとutilityをconstexprにする提案。

前の提案はcstring(主にmemmove/memset/memcmp)もconstexprにする提案だったが、cstringに手を入れるのは見送られた。かわりに、compiler intrinsicsなどの方法で実現する方向に調整された。

さて、既存のC++標準ライブラリの実装を見てみると、libstdc++はcompiler intrinsicsを使っているのでこのままconstexprに対応可能で、libc++はcstringを使っているので書き換えが必要だ。また、libc++はgotoを使っているのでこの点でも書き換えが必要となる。

stable_partition, inplace_merge, stable_sortは、メモリ確保、placement newによる構築、unique_ptrの使用があるので、constexprからは除外する。

shuffleとsampleはuniform_int_distributionを使うため、constexprからは除外する。

[PDF] P0214R6: Data-Parallel Vector Types & Operations

SIMDプログラミングのためのベクトル型の提案。なんだかすごく使いづらそうな設計だ。

[PDF] P0233R6: Hazard Pointers: Safe Reclamation for Optimistic Concurrency

ハザードポインターライブラリの提案。ハザードポインターはIBMのMaged M. Michaelによって考案され、IBMのMaged M. Michaelによって特許申請された。最終的に特許申請は取り下げられた。ところでこの提案文書の執筆者はIBMのMaged M. Michaelである。この提案が特許汚染されていないかどうか注意深い検証が必要だ。

ISO国際標準規格には特許汚染された技術を持ち込むべきではない。ましてや特許汚染の前科がある人間によって提案された機能は眉に唾をつけてみるべきだ。

[PDF] P0237R9: Wording for fundamental bit manipulation utilities

Nビットの符号なし整数型をN個のbit要素が入っているコンテナーだとみなし、ビットに対するイテレーターを提供するイテレーターアダプターライブラリ、bit_iteratorの提案。

ドワンゴ広告

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

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

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

2017-10-23

インデックス付きrange-based forに必要なのはネストされた構造化束縛ではなくてif constexprだった

親愛なるC++読者諸君、私がC++17を流暢に使いこなす江添亮である。前回、ネストされた構造化束縛がほしいと書いた。

本の虫: インデックス付きRange-based for文を実装したらネストされた構造化束縛が欲しくなった

このブログを公開してすぐ、同僚からwith_index側でpairを開けばいいのではないかと言われた。たしかにそのとおりだ。早速実装した。その結果、以下のコードが通るようになった。


int main()
{
    std::map<int,int> m = { {1,1}, {2,2},{3,3} } ;

    for ( auto[ i, key, mapped ] : with_index(m) )
    {
        std::cout << i << key << mapped ;
    }
}

その実装の骨子は以下の通り。


template < typename T >
struct is_pair
    : std::false_type { } ;

template < typename T1, typename T2 >
struct is_pair< std::pair<T1, T2> >
    : std::true_type { } ;

template < typename T >
constexpr bool is_pair_v = is_pair<T>::value ;

template < typename Iterator  >
class with_index_iterator
    : public Iterator
{

public :
    auto operator *() const noexcept
    {   // ここが重要
        if constexpr ( is_pair_v< typename std::iterator_traits<Iterator>::value_type > )
        {
            auto & pair = *static_cast<Iterator const &>(*this) ;
            return std::make_tuple( i, pair.first, pair.second ) ;
        }
        else {
            return std::make_pair( i, *static_cast<Iterator const &>(*this) ) ;
        }
    }
} ;

重要なのはif constexprだ。constexpr ifによって、わざわざクラステンプレートを書かずともコンパイル時条件分岐ができるようになった。これでメタプログラミングがとても書きやすくなった。

なお、この実装では以下のようなコードは通らない。

int main()
{
    std::map<int, std::pair<int,int> > m = { {1,{1,1}}, {2,{2,2}},{3,{3,} } ;

    for ( auto[ i, key, m1, m2 ] : with_index(m) )
    { }
}

再帰的なテンプレートメタプログラミングをすることにより、何段階にネストされようとも開くことができるwith_indexは実装可能だ。その実装は読者への課題とする。

また、構造化束縛がpairの他にも対応しているtupleやtuple_sizeとtuple_elementとgetに対応した型のネストへの対応も、読者への課題とする。

int main()
{
    std::map<int, std::tuple<int,int> > m = { {1,{1,1}}, {2,{2,2}},{3,{3,} } ;

    for ( auto[ i, key, m1, m2 ] : with_index(m) )
    { }
}

問題は、構造化束縛が対応しているクラスを開くことができない。


struct user_defined_pair
{
    int x ;
    int y ;
} ;

std::map< int, user_defined_pair > m = { {1,{1,1}}, {2,{2,2}},{3,{3,} } ;

これはどうしようもない。とはいえ、実用上はこれでいいのではないか。

with_indexの完全な実装は以下の通り。

template < typename T >
struct is_pair
    : std::false_type { } ;

template < typename T1, typename T2 >
struct is_pair< std::pair<T1, T2> >
    : std::true_type { } ;

template < typename T >
constexpr bool is_pair_v = is_pair<T>::value ;



template < typename Iterator  >
class with_index_iterator
    : public Iterator
{
    std::size_t i = 0 ;

public :

    with_index_iterator( Iterator iter )
        : Iterator( iter )
    { }

    auto & operator ++()
    {
        ++i ;
        this->Iterator::operator ++() ;
        return *this ;
    }

    auto operator *() const noexcept
    {
        if constexpr ( is_pair_v< typename std::iterator_traits<Iterator>::value_type > )
        {
            auto & pair = *static_cast<Iterator const &>(*this) ;
            return std::make_tuple( i, pair.first, pair.second ) ;
        }
        else {
            return std::make_pair( i, *static_cast<Iterator const &>(*this) ) ;
        }
    }

} ;

template < typename Range >
class with_index
{
    Range & range ;

public :
    with_index( Range & range )
        : range(range)
    { }

    auto begin() const
    {
        return with_index_iterator{ std::begin(range) } ;
    }
    auto end() const
    {
        return with_index_iterator{ std::end(range) } ;
    }

} ;

ドワンゴ広告

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

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

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

インデックス付きRange-based for文を実装したらネストされた構造化束縛が欲しくなった

親愛なるC++14以前の古臭いC++を書く読者諸君。疑う余地なく、私がC++17を華麗に使いこなす江添亮である。

私のC++17参考書も余裕で書き終わり、後は出版を待つだけだ。私の中で、C++というのはもうすっかりC++17になってしまい、以前のC++のことは忘れてしまった。いまさらC++14のような使いづらい時代遅れのC++を書きたくはない。時代はいよいよC++17が当然になったと言えよう。

私のC++17参考書はGPLv3という自由なライセンスで提供される究極の電子書籍だ。これから紙書籍、プロフェッショナルに組版された電子書籍も出版される予定になっているので、読者は読まないという法はない。

EzoeRyou/cpp17book: C++17参考書

ところで、インデックス付きRange-based for文がほしいとさえずっていた。というのも、レンジの要素のイテレートを手で書きたくはないし、インデックスのインクリメントも手で書きたくないからだ。

template < typename Container >
void f( Container & c )
{
    // 要素のイテレートは手動
    // インデックスのインクリメントは手動
    for (   auto i = std::size_t(0),
            iter = std::begin(c), end = std::end(c) ;
            iter != end ; ++iter, ++i )
    {
        // iはインデックス
        // *iterは要素 
    }
}

std::for_eachやRange-based for文を使うことにより、要素のイテレートは手で書かずにすむ。しかし、インデックスのインクリメントは依然として書かなければならない。

template < typename Container >
void f( Container & c )
{
    {
        std::size_t i = 0 ;
        for ( auto element : c )
        {
            // iはインデックス
            // elementは要素
            ++i ; // 手動インクリメント
        }
    }

    std::for_each( std::begin(c), std::end(c),
        [i = std::size_t(0)](auto element) mutable
        {
            // iはインデックス
            // elementは要素
            ++i ; 手動インクリメント
        } ) ;
}

これではfor文より読みやすさ、間違いにくさの点で悪化しているではないか。

ところで、C++17では構造化束縛が追加された。


// クラステンプレートのコンストラクターの実引数からの推定も追加された
std::pair p(1,2) ;
auto [a,b] = p ;
// 以下と同じ
// auto a = p.first ;
// auto b = p.second ;

構造化束縛は、もちろんRange-based for文でも使える。


int main()
{
    std::map<int,int> m = {{1,1},{2,2},{3,3}} ;

    for ( auto [key, mapped] : m )
    {
        std::cout << key << mapped ;
    }
}

このコードは期待通りに動く。この程度のコードは、すでにC++17プログラマーである私にとってごく自然で当然のコードだが、未だに旧態依然のC++14以下にとらわれている読者には垂涎のコードだろう。

ということは、コンテナーをラップして、インデックスカウンターを持ち、operator ++でインデックスをインクリメント、operator *でstd::pair<std::size_t, reference>を返すようなラッパーを書けば、Range-based for文にインデックスが追加できるのではないか。

早速そのようなラッパー、with_indexを書いてみた。


int main()
{
    std::vector v = {1,2,3,4,5} ;

    for ( auto[ i, element ] : with_index(v) )
    {
        std::cout << i << element ;
    }
}

いける。これは使える。

しかし、問題がある。構造化束縛はネストできないので、std::mapに使うと以下のようになってしまう。

int main()
{
    std::map<int,int> m = { {1,1},{2,2},{3,3} } ;

    for ( auto[ i, pair ] : with_index(m) )
    {
        auto [key, mapped] = pair ;
        std::cout << i << key << mapped ;
    }
}

C++にもネストされた構造化束縛がほしい。

// C++ではない
int main()
{
    std::pair< int, std::pair<int,int> > p = { 1, {2,3} } ;

    // これがほしい
    auto [a, [b,c]] = p ;
}

ちなみに、with_indexの実装は以下の通り。

template < typename Iterator  >
class with_index_iterator
    : public Iterator
{
    std::size_t i = 0 ;

public :

    with_index_iterator( Iterator iter )
        : Iterator( iter )
    { }

    auto & operator ++()
    {
        ++i ;
        this->Iterator::operator ++() ;
        return *this ;
    }

    auto operator *() const noexcept
    {
        return std::pair<
            std::size_t,
            typename std::iterator_traits<Iterator>::reference >
        { i, *static_cast<Iterator const &>(*this) } ;
    }

} ;

template < typename Range >
class with_index
{
    Range & range ;

public :
    with_index( Range & range )
        : range(range)
    { }

    auto begin() const
    {
        return with_index_iterator{ std::begin(range) } ;
    }
    auto end() const
    {
        return with_index_iterator{ std::end(range) } ;
    }

} ;

ドワンゴ広告

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

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

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

2017-10-20

Ubuntu 17.10にアップグレードした

Ubuntu 17.10がリリースされた。

ArtfulAardvark/ReleaseNotes - Ubuntu Wiki

今回のリリースでは、デスクトップ環境がUnityからGnomeに変わった。同時に、X.orgではなくWaylandに変わっている。

このため、Ubuntuのデスクトップ環境の使用感がだいぶ変わっている。まず、GnomeはUnity風の操作感を再現するために、やや手が入っている。具体的にはSuper+数字でランチャーに登録されているソフトウエアのウインドウを選択できたりする。

残念なことに、Global MenuやHUDは再現されていなかった。

Waylandに移行したので、日本語入力環境が大変不便になった。fcitxはWaylandに対応していないので使えない。使えないが、そのことは警告されないので、fcitxを使っているUbuntu 17.04からアップグレードすると、日本語が入力できなくなる。iBusに切り替える必要がある。iBusはキーボードレイアウトとかな漢字変換機能を持つIMEをごちゃまぜにしているので本当に使いづらい。しかも、変換候補のウインドウが、カーソル位置ではなく画面左上に出る。極めてつらい。

私は事前に調べているからいいものの、これは何も知らない人がアップグレードしたら日本語入力ができずに詰みそうだ。

特に興味深いパッケージのバージョンという点では、Linuxカーネルが4.13に、GCCが7.2.0に、Clangが4.0.1.6に、Neovimが0.2.0になった。

GCCとClangのバージョンが上がったので、これでfilesystemなどの一部のライブラリを除いて、どちらもC++17をある程度実装したコンパイラーになった。

ただし、現在libc++にはxlocale.hをincludeするという不具合がある。xlocale.hは標準のヘッダーではなくglibcの内部ヘッダーであり、しかもそのコメントには、"This file is not standardized, don't rely on it, it can go away without warning"と書いてある。

sourceware.org Git - glibc.git/commit

libc++がなぜxlocale.hをincludeしているのか全くわからない。実装を読んだが、単にincludeしているだけだ。なので、とりあえず空のxlocale.hファイルを作り、そのファイルへのディレクトリーを-Iで追加して対処した。

また、メインでは使っていないDellのLatitude E7470でUbuntuがうまく動かない問題は、Ubuntu 17.10でも解決しなかった。まずアップグレードが途中で失敗する。

DellのLatitude E7470でUbuntuがうまく動かない問題は、未だに原因がわからない。以下のような問題がある。

Live環境のブートが遅い。ログを見ると、pwconvが/etc/shadow-のパーミッションを0600に変更しようとしてエラーを出し、パッケージリストを読み込むのに時間を要し、regenerating SSL certificatesでまた時間を要する。放置しても絶対に進まず、キーボードを適当にワシャワシャ叩くと進む。まるで/dev/randomへのエントロピーが十分にたまるまで待っているかのような挙動をする。

初回ログイン時に数回画面が暗転する。

突然フリーズする。マウスカーソルは動くがそれ以外の操作を何も受け付けない。ttyの変更すらできない。文字入力をしているときにフリーズしやすい気がする。

cat /dev/urandomが何故か目視できるほど遅い。urandomなのに遅い。

grub-updateが遅い。

apt upgradeしたときの"procescing triggers for man-db"が遅い。

なので実用にならないのだが、一応維持している。Ubuntuの欠陥なのかDell Latitudeの欠陥なのか、個体の欠陥なのかわからないが、私は個体の欠陥だと思っている。しかし、memtest86+は何の問題もなく何パスも通るので、メモリではなさそうだ。また、ストレージへの読み書きも遅いわけではない。単純なベンチマークやストレステストで問題が見つからないのでよくわからない。

2017-10-19

江添ボドゲ会 10月22日

10月22日に以下の通り、自宅でボドゲ会を行います。

江添ボドゲ会 10月22日 - connpass

2017-10-16

GitHubで他人のプルリクエストに対しコンフリクト解消や追加の修正を行いつつマージする方法

読者がGitHubで何かを公開しているとしよう。そのレポジトリに対して他人がプルリクエストを送ってきた。なかなか良さそうな変更だ。早速マージしたい。

しかし、残念なことにそのプルリクをそのままマージすることができない。なぜならば、

  • コンフリクトを起こしている
  • 追加の修正が必要だ

こういう場合、大規模なプロジェクトや、PR主が職場の同僚や開発仲間であった場合、PR主に修正を依頼するものだ。しかし、個人的な小規模なプロジェクトなのでPR主はPRを出したまま返事がない。

こういう場合に、PRをマージするにはどうすればいいのか。答えは簡単で、プルリクエストが裏でやっているgit操作を自分のローカルでやればいいのだ。

まず、該当のPRのGitHub上のページの、「プルリクエストをマージ」ボタンの横に、コマンドライン操作を表示(view command line instructions)というリンクがあるはずだ。これをクリックすると、プルリクエストに相当する作業を、ローカルのコマンドでやる方法が表示される。その指示に従うだけでよい。

ローカルのコマンドでやる方法は、以下のような意味になっている。

# ローカルで新しくブランチを作る
git checkout -b example master
# 新ブランチにPR先の変更を入れる
git pull git://example.com example

# 必要に応じてローカルでコンフリクト解消と編集をしてコミット

# masterブランチに切り替え
git checkout master
# masterブランチにマージ
git merge --no-ff example
# 結果をGitHubレポジトリにpush
git push origin master

マージ操作の後はexampleブランチはいらないのでgit branch -d exampleで消してよい。

これによって、PRをマージしたという歴史は正しくgitレポジトリに反映される。GitHubのプルリクエストの方は何もする必要はない。自動的にマージされた扱いになっている。

GitHubのWebページ上でプルリクエストをマージするボタンを押すというのは、このgit操作をGitHubがリモートレポジトリ上でやってくれているだけの話だ。

プルリク、プルリクエスト、PR, Pull Request、GitHubに特有の複数人のgit操作を楽にするための概念だ。PRは面倒で複雑なgit操作をユーザーから隠している。しかし、こういう問題が発生した時、裏で行われているgit操作を知らない場合、途方に暮れてしまう。その結果、masterにマージしてから追加の編集を行うとか、手作業で同様の編集をするなどといった日付zipと何ら変わらない運用が行われてしまうこともある。

この記事はできるだけ簡潔に解説する目的で書いた。git強者な読者であれば、gitには同じ操作をもっと強力にやる方法が用意されているなど、俺のお気に入りのgitフロントエンドや拡張ツールを使えばもっと強力な操作が行えるなどと、言いたいことは様々あるかもしれないが、これは初心者用の解説だ。

2017-10-13

C++17の参考書を書き上げた

C++17の新機能のほぼすべてを解説した参考書を書き上げた。

GitHub: EzoeRyou/cpp17book: textbook for C++17

GitHub Pages: C++の新機能

この参考書は、後ほどアスキードワンゴから出版される予定になっている。

内容としては2017年に制定された新しい標準規格、C++17に追加された新しいコア言語と標準ライブラリのほぼすべてを解説した内容になっている。

C++17には数学関数も追加されていて、これの執筆には読者から多大な貢献を得た。

C++17の新機能: 数学の特殊関数群

この本はGPLv3でライセンスされ、紙書籍での出版も、GPLv3で行うことを予定している。

さて、C++17はすでに規格制定され、C++20まではまだ少し時間がある。この暇に、今まで得たC++の知識を使って本を書くべきだと思ったので、次も本を書くことに注力したい。今考えているのはC++の入門書だ。

入門書という分野について、私にはあまり好ましい印象がない。世の中のいわゆる入門書をめくると、なにやらSI屋がよろこぶようなエクセル方眼紙エビデンスよろしくスクリーンショットをベタベタと貼り付けて、無駄に紙面を50ページも100ページも使い、結局何を説明しているかというと、Microsoftの不自由なVisual Studioのインストール方法だけを説明していたりする。完全に訳がわからない。私の書く入門書はそのような本にはしない。

そもそも、今C++の入門書を必要とする人間は、一体どういう環境にあるのだろう。

この2017年にC++入門者の筆頭に上がるのは競技プログラマーだ。彼らは大抵のオンラインジャッジシステムでサポートしていてパフォーマンスが出て必要なアルゴリズムを書き起こせる言語であるC++を使う。興味深いことに、彼らはC++にある素晴らしい機能の筆頭に、next_permutationという標準ライブラリの存在を挙げる。next_permutationを実務で使う状況というのはまれにしか起こらないと思うのだが、不思議なことだ。

既存の自由ソフトウェアに貢献したいが、そのソフトウェアがC++で書かれている場合、これはC++を学ぶ必要がある。そういう人もいるだろう。

仕事でC++を書く必要が出てきて学ぶという人もいるだろう。C++が使われる仕事として一番わかり易いのは、不自由なゲーム専用機などの組み込み機器だと思われる。

すでにC言語は知っているが、C++を学びたいという人。15年前ならばそういう人はいくらでもいたが、果たしてこの2017年にいるのだろうか。ただ、例えばLinuxカーネルの開発に参加したい場合、これはC言語を学ぶしかない。カーネル開発者は未だにC言語が必要なので学び、C++を知らないが学びたいという人は多いのかもしれない。

これを考えると、次に書くべきC++入門書は、プログラミング入門書である必要はない。対象読者はすでに別の言語でプログラミングの基礎にある程度触れていることを想定して書いてもよいはずだ。つまり、環境構築や、変数とは箱のようなものであるといった比喩表現はいらない。

ドワンゴ広告

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

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

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

2017-10-08

オーストラリア警察が世界最大の児童ポルノサイトを11ヶ月運営していたことが判明

VG exposed the largest child sexual abuse forum. It was run by the police.

ノルウェイのタブロイド紙のヴェルデンス・ガング(VG)は、Tor経由でアクセスできるいわゆるダークウェブの中で世界最大の児童ポルノサイトであるChilds Playは、オーストラリア警察によって運営されていたことをつきとめた。この顛末は倫理的にも技術的にも興味深い。

この児童ポルノサイトは、当時ダークウェブの児童ポルノサイトの中でも世界最大級の規模を持っていた。各国の警察は様々な捜査の上、このサイトを運営していた二人の逮捕に至った。そして、Webサイトは、各国警察相談の上、おとり捜査が合法な国、オーストラリア警察、アルゴスの手に委ねられた。アルゴスはWebサイトのホスティングをオーストラリアのレンタルホスティングサービス、Digital Pacificに移し、そこでWebサイトの運営を続けた。

児童ポルノサイトの運営者を逮捕した後、警察がWebサイトを運営し続けておとり捜査に使うというのはよくあることだ。VGのまとめによれば、すでに以下のWebサイトが警察によって運営されていたことが知られているという。

  • Elysium: ドイツ、BKAにより数日アクセスされた
  • Playpen: USA, FBIにより2週間運営
  • The Giftbox Exchange: EUにより約1ヶ月運営
  • The Love Zone: オーストラリア、アルゴスにより6ヶ月運営

今回、オーストラリアの警察組織アルゴスによって、当時世界最大だった児童ポルノサイトのChilds Playは11ヶ月運営された。

児童ポルノサイトをおとり捜査のために運営することは様々な倫理上の問題を引き起こすが、今回の例はさらに倫理上の疑問点がある。Childs Playの運営者は頻繁にフォーラムにあらわれていた他に、一ヶ月ごとに必ず新作の児童ポルノを提供していたのだった。運営者が逮捕されたことを利用者にさとられないよう、オーストラリア警察の捜査官は運営者の語彙を使い、書き言葉をまねてフォーラムへの書き込みを続けていたが、ついに次の新作児童ポルノを投稿しなければならない時期にきた。そこで、オーストラリア警察はすでに押収していたそのWebサイトにはない児童ポルノを投稿して運営を継続した。

これはおとり捜査が違法で、法律の記述は、単に潜入捜査員の身を守るために本来ならば犯罪になる行為(麻薬の購入や違法な武器の受け渡し、競馬競輪競艇オートレースのノミ屋の脚)をすることができると定めているもので、おとり捜査を許可したものではない日本に住む筆者の倫理観では理解ができない。

結局、一定の割合で児童ポルノを求める人間がいるのであれば、児童ポルノサイトを運営し続ければ犯罪を摘発をし続けることができるわけだ。犯罪の摘発はオーストラリア警察にとって評価対象だ。すると、児童ポルノは評価を生み出す装置となり、継続して運営するインセンティブが生じる。今回、11ヶ月の長きに渡り押収した児童ポルノサイトの運営を警察が続けたのは、このようなインセンティブのせいだろう。ましてや押収した児童ポルノサイトにはなかった児童ポルノをよそから持ってきてオーストラリア警察が公開しているというのは、もはやオーストラリア警察が犯罪を行っているのと同じではないか。オーストラリアの法ではおとり捜査が認められているのでオーストラリア警察の行為はオーストラリア国内では違法ではないということになるのだが。

さて、倫理面についてはこのぐらいにして、技術面に移る。

ノルウェイのタブロイド紙であるVGはChils Playがオーストラリア警察の手によって運営されていることを突き止めたのだが、これは至って合法的な方法で行われた。

オーストラリア警察アルゴスは、WebサイトのホスティングをオーストラリアのレンタルホスティングサービスのDigital Pacificに移した。しかし、WebサイトへのアクセスはTor経由でなければ行えないため、物理サーバーのIPアドレスはわからない。VGは当初、フォーラムの投稿から運営元を突き止めようとしたが、Webサイトの利用者の一部は簡単に特定できたものの、元運営者は注意深かく、運営を引き継いだオーストラリア警察も注意深かったので、身元はわからなかった。

そこでVGは、もっと古典的な方法で物理サーバーのIPアドレスを調べることにした。

Webサイトの実装のほとんどは注意深くTor経由で行われていたが、うっかり物理サーバーから直接アクセスしている箇所があったのだ。

Webサイトはユーザーがアカウントのプロフィール画像を設定できるようにしていたが、この設定では、URLを指定することができた。URLから画像をダウンロードするのはTorを経由せず、物理サーバーが直接行ってしまっていた。

これによってVGはDigital PacificのIPアドレスであることを突き止めたが、まだここで終わりではない。Digital Pacificがホストしているサーバーは単なるプロクシー、VPN、あるいはTor exit nodeかもしれないからだ。

そこでVGはDigital PacificのサーバーがVPNではなくWebサイトを直接ホストしているかどうかを判定するために、いわゆるサイドチャネル攻撃を行った。Digital Pacificのサーバーをレンタルし、プロファイル画像のURLをそのサーバーに向けるようにしたのだ。そして、サーバー間のラウンドトリップ時間を計測した。Digital Pacificが単なる中継サーバーならば、ラウンドトリップ時間は同一データセンター内よりはるかに長いはずだ。こうして同一データセンター内で処理が行われていると思しき短いラウンドトリップ時間を確認した。

そしてもう一つ、サーバー間のMTUとパケット分割を計測することで、同一のローカルエリア・ネットワークに存在する可能性が高いことを確認した。

追記:Digital Pacificの該当のIPアドレスをレンタルしているのがオーストラリア警察であるとどうやって判明したかも、VGの元記事に書いてある。VGの記者はシドニーにあるDigital Pacificに直接取材をした。Digital Pacificの創業者であるAndrew KoloadinはVGの説明を聞き、誰にリースしているのかを調査したところ、オーストラリア警察に行き着いた。

「このようなものを我々のサーバーに保持することは契約に反する。警察は我々に事前に相談するべきであった。しかし、そうはしない理由はわかる。秘密捜査とやらだろう」 「貴社のサーバーに警察が性的犯罪物を置くことについてどう思われますか?」
「犯罪者は頭がよく、警察をかわすシステムの設置方法に精通していた。なので、警察も同じぐらい頭が良くなければならないし、実際そのようだ。しかし、警察が我々の及び知らないところでこういうことをやっているのは気に入らない。」

そして、VG記者は次の日にオーストラリア警察に取材を申し込み、二人の捜査官と喫茶店で話をすることになる。

この件は倫理と技術の両方の点で面白い事件だった。筆者はおとり捜査には反対の立場だ。理由は、児童ポルノサイトが存在すれば、そこにアクセスする人間が一定の割合で存在する。するとおとり捜査を続ければ続けるほど、検挙ができるということになる。検挙は成果でありインセンティブとなる。おとり捜査を続ければ続けるほど成果が出るのであれば、インセンティブに従って、おとり捜査は発覚するまで永久に続けるべきであるということになる。結果として今回のオーストラリア警察による児童ポルノサイトの運営は11ヶ月も続けられた。これではミイラ取りがミイラになったようなものだ。しかし、警察のおとり捜査によって児童ポルノサイトが存在しなければ、そのような犯罪は本来発生しなかったはずだ。

このようなインセンティブの問題のため、おとり捜査は違法となるべきだ。

2017-10-05

VS CodeがDOMによるターミナル実装のパフォーマンスを改善できなかったためCanvasに変更

Integrated Terminal Performance Improvements

Electronという史上まれに見るそびえ立つクソのようなGUIプラットフォーム上で実装されているVS Codeが、ターミナルの実装をDOMによるものからCanvasによるものに変更したそうだ。これは、DOMによる実装ではパフォーマンスの改善が十分にできなかったからだという。

DOMでターミナルを実装する際の問題ごととして、テキスト選択、テキストアライメント、GC、パフォーマンスを上げている。

テキスト選択:ターミナルのテキスト選択を実現するためにDOMのテキスト選択の挙動をだいぶ上書きしなければならない。

テキストアライメント:一部の文字はモノスペースになってくれず、workaroundとして一文字ごとに固定長のspanで包む必要があるが、これはパフォーマンス上よろしくない。

GC:DOMでターミナルを実装するためにメチャクチャなことをするのでGCによってパフォーマンスが劣化する。オブジェクトをプールすることでなるべくDOMを使いまわしGCを低減する泥臭いハックをしたが、限界がある

パフォーマンス:色々と頑張ったが、結局パフォーマンスは悪かった。

そして結局、要素を組み合わせてレイアウトを決定するという処理だけで16.6ms以上かかる場合もあり、60fpsを達成できないので、ターミナルをDOMで実装するのは不向きだという結論に達したそうだ。

フルHDのデスクトップ画面をキャプチャしてH.264などにエンコード、デコードすることをリアルタイムで行えるほどコンピューターが高速化したこの2017年にターミナルを60FPSで実装するのに苦労しているのはすさまじい。

やはりElectronは悪い文明 粉砕する!

2017-09-29

C++のfilesystemライブラリが膨大すぎる

C++17の参考書はほぼ書き終えて、あとはfilesystemライブラリの解説を残すだけになっている。

EzoeRyou/cpp17book: textbook for C++17

ファイルシステムライブラリは、ext4とかbtrfsのようないわゆるファイルシステムに対するライブラリではなく、ディレクトリとファイルに対する操作を提供するライブラリだ。具体的にはファイルパスの文字列処理や、ファイルのコピーやリネーム、ディレクトリ構造のトラバースといった雑多なファイルシステム操作を提供する。

C++のファイルシステムライブラリは、原則としてPOSIX互換になっている。POSIXの規定するライブラリをモダンなC++風のライブラリとして設計したものだ。例えば、カレントディレクトリにあるファイルをすべて表示するプログラムは以下のように書ける。

#include <filesystem>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    using namespace std::filesystem ;

    directory_iterator iter("."), end ;
    std::copy( iter, end, std::ostream_iterator<path>(std::cout, "\n") ) ;
}

C++らしく、ディレクトリー構造をイテレーターでたどることができる。イテレーターなのでアルゴリズムに突っ込むこともできる。

参考書としてファイルシステムライブラリを解説するにあたって、量が膨大すぎるという問題がある。POSIXのファイルシステム操作をカバーするライブラリなのだから膨大になるのは仕方がないが、まともに解説したのでは100ページを確実に超える解説が必要になる。

しかも、絶対パスを得るabsolute(path)とかcopyとかcreate_directoryとかcreate_symlinkとか、自明で雑多な関数が多すぎる。

これらの関数をいちいち解説しても、リファレンスにしかならない。リファレンスならばC++コンパイラーに付属のドキュメントを読めばいいはずだ。

そこで、今書いている参考書では、ファイルシステムライブラリのすべてを解説するのではなく、概要を解説しようと思う。

しかし、概要と言ってもやはり量が膨大で、エラー処理もあるし、なによりクラスpathの初期化だけで、C++が規定している文字列エンコードの話から始めなければならない始末だ。

path::value_typeがどのような文字型をもつのかは未規定で実装に依存する。pathはできるだけポータブルなコードを書けるように、文字コードの変換をサポートしている。


int main()
{
    using namespace std::filesystem ;

    // ネイティブナローエンコード
    path p1( "/dev/null" ) ;
    // ネイティブワイドエンコード
    path p2( L"/dev/null" ) ;
    // UTF-16エンコード
    path p3( u"/dev/null" ) ;
    // UTF-32エンコード
    path p4( U"/dev/null" ) ;
}

C++では、char型がネイティブナローエンコードとUTF-8エンコードの両方の文字型を兼ねているので、char型はネイティブナローエンコードであると解釈される。ネイティブナローエンコードがたまたまUTF-8ならばUTF-8を渡してもいいが、そうではない場合、おそらく動かない。


int main()
{
    using namespace std::filesystem ;

    // ネイティブナローエンコードとして解釈される
    path p(u8"ファイル名") ;
}

このコードは、ネイティブナローエンコードがUTF-8ではない場合、動く保証がない移植性の低いコードだ。

ファイルシステムライブラリは、移植性が高いUTF-8文字列でファイルパスを扱う方法としてu8path(Source)が用意されている。


int main()
{
    using namespace std::filesystem ;

    path p = u8path(u8"ファイル名") ;
}

こういった細かい落とし穴を解説していくだけでページ数がかさむ。早く完成させたい。

2017-09-28

Googleの公開したAbseilライブラリの価値がわからない

先日、GoogleはAbseilというライブラリを公開した。

abseil/abseil-cpp: Abseil Common Libraries (C++)

その中身を見てみたが、どうもその価値がよくわからない。

その大半は、C++14/17風の標準ライブラリのC++11による実装だ。C++14はすでにGCCもClangも実装し終えており、C++17の完全な実装も時間の問題だ。このようなライブラリを使うことはむしろ最新のC++規格の普及を妨げる。

曰く、「Abseilは完全なC++14/17実装では標準ライブラリのtypedefになる」と。しかし、それで問題が解決するのであればさっさとC++コンパイラーのバージョンを挙げたほうがよい。

containerには変わり者がある。inlined_vector<T, N>はstd::stringのSSO(Small String Optimization)をvectorで実装したものだ。N個の要素のストレージはvectorのオブジェクトの中に確保されるので、動的メモリ確保がいらない。N個を越える要素を扱うときには動的にメモリが確保される。注意しなければならいのは、N個を超えた要素を扱うときはvector内部に確保したN個のストレージは無駄になるということだ。

fixed_arrayはクラスオブジェクトに256バイトのストレージを確保し、その範囲に収まる場合はそちらを使うことで動的メモリ確保を回避するクラスのようだ。

我々はC++の最新の規格を実装したC++コンパイラーをいち早く使えるように努力すべきであり、それにはMicrosoft WindowsとRHELを使わないことがまず第一歩となる。

2017-09-25

C++の未定義の挙動で呼ばれないはずの関数が呼ばれる場合

Krister Walfridsson’s blog: Why undefined behavior may call a never-called function

以下のようなコードをClangでコンパイルすると、

#include <cstdlib>

typedef int (*Function)();

static Function Do;

static int EraseAll() {
  return system("rm -rf /");
}

void NeverCalled() {
  Do = EraseAll;  
}

int main() {
  return Do();
}

Clangは以下のような最適化されたコードを吐く。


main:
        movl    $.L.str, %edi
        jmp     system

.L.str:
        .asciz  "rm -rf /"

これは以下のようなコードと同じだ。


#include <cstdlib>

int main() {
    return system("rm -rf /") ;
}

なぜなのか。

もちろん未定義の挙動のためだ。static変数Doは、static変数なのでまず0で初期化される。値が0の関数ポインターを関数呼び出しした場合、挙動は未定義だ。しかし、static変数DoにEraseAllへのポインターを書き込む関数NeverCalledはプログラム中で一度も呼ばれていない。なぜこのコードでEraseAllが呼び出されてしまうのか。もちろん未定義の挙動のためだ。

関数ポインターを経由した関数の呼び出しはコストがかかる。できれば関数ポインター経由ではなく直接呼び出したい。呼び出す関数がわかっているのであればインライン展開もできる。

さて、Clangが変数Doの取りうる値について全プログラムを調べたところ、0と&EraseAllのいずれかであることが判明した。値が0の場合、関数ポインター経由の関数呼び出しの挙動は未定義になる。未定義の挙動はありえないのでその場合は除外してよい。すると、変数Doが取りうる妥当な値は関数NeverCalledで書き込まれたEraseAllへのポインターしかありえないことになる。すると、Do()はEraseAll()と同じだとみなしてよい。これによって呼び出す関数が判明したので、インライン展開もできる。

という理由によって、未定義の挙動を利用した最適化の結果、Clangでは本来呼ばれないはずの関数が呼ばれてしまう。

このような取りうる値について全プログラム中を調べた結果の最適化は、virtual関数呼び出しを可能な文脈では通常の関数呼び出しにするなど、有益な最適化に繋がっている。

教訓としては、未定義の挙動を引き起こさないようにしようということだ。

ちなみに、元記事の筆者は、追加の記事でさらなる最適化の可能性に言及している。

Krister Walfridsson’s blog: Follow-up on “Why undefined behavior may call a never-called function”

最初のコードに以下のコードが追加された場合

static int LsAll() {
  return system("ls /");
}
void NeverCalled2() {
  Do = LsAll;
}

return Do() ;は、以下のように最適化されることが理論上可能だ。


if (Do == LsAll)
  return LsAll();
else
  return EraseAll();

これは条件分岐をしているので一見無意味な最適化のようにみえるが、もし関数のインライン展開ができて条件分岐を上回る最適化になるのであれば、最適化として適切になる。

現在、Clangはこの最適化をしていないが、GCCでvirtual関数呼び出しの最適化を-fdevirtualize-speculativelyオプションを指定して行わせた場合、virtual関数呼び出しについては似たようなコードを吐くので、可能性としてありえなくはない。

2017-09-19

W3Cよさらば! 遂に協力の方途尽く W3C、邪悪なDRMを採択し 我がEFF堂々退場す

World Wide Web Consortium abandons consensus, standardizes DRM with 58.4% support, EFF resigns / Boing Boing

EFFはW3Cが可決したWebにおけるDRM標準規格の取り下げを訴えた。W3Cにおいて可決された規格の取り下げの訴えは初めてのことである。W3Cは会議の結果、メンバーのうちの過半数である58.5%の賛成をもって、過半数によるコンセンサスとしてDRM規格の取り下げを却下した。これはW3Cのメンバーに利用者の自由と権利をないがしろにした不自由陣営が多いためである。

これを受けてEFFは、W3CはもはやオープンなWeb規格を制定する場ではないと判断し、即日W3Cを脱退した。

An open letter to the W3C Director, CEO, team and membership | Electronic Frontier Foundation

これは正しい判断だ。私が平素から主張しているように、桜の花も散り際が肝心で、いまこそ自由精神の発揚が必要だ。Web規格は誰でも実装できるように公開されているべきで、実装できないような非公開の規定を含む規格はもはや規格ではない。邪悪な不自由な陣営に汚染されたW3CはもはやWebの標準規格を定める場所ではない。

ところで、1933年の日本の国際連盟の脱退に際し、朝日新聞の「連盟よさらば」という見出しの記事の全文を読みたいのだがWeb上には詳細がみつからない。誰か心当たりの人はいないだろうか。

2017-09-18

Linux財団のトップ、「2017年はLinuxデスクトップの年だ」というスピーチのスライド資料を映すのにMacを使って炎上

iTWire - Linux Foundation head proclaims year of Linux desktop – from a Mac

Linux財団のトップ、Jim Zemlinは、オープンソースサミット2017年の基調講演において、「2017年はLinuxデスクトップの年だ」という趣旨の発表を行ったが、そのときにスライド資料を映すのにMacを使ったため炎上している。

Jim ZemlinがMacを使っているのは今に始まった話ではない。例えば4年前の2013年には、Linux開発者として有名な Matthew Garrettにもネタにされている。

そして、今回のことも皮肉られている。

Linuxやオープンソースソフトウェアの普及と発展が目的のLinux財団のトップのJim Zemlinが、オープンソースがテーマの会合において、今年はLinuxデスクトップの年だという趣旨の発表をする際に、スライド資料の投影にLinuxカーネルを使っていないというのは、皮肉も皮肉で炎上もやむなしと言えるのではないか。

たとえば、AppleのトップであるTim CookがMacの新製品を発表するのに使うスライド資料の投影に、マイクロソフトのSurfaceでマイクロソフトのWindows OSを動かしマイクロソフトのパワーポイントを使った場合、これは炎上するだろう。フォードのトップが新車の発表会の会場にトヨタの車で乗り付けてきたらやはり炎上するだろう。

一般に、公の場で特定の団体のトップが団体の主義主張を発表するという肝心な場面で、その主義主張に真っ向から反する言動を発表中に行っているとするならば、それは悪い意味で耳目を集めるに決まっている。

なお、この文章はもちろんGNU/Linuxで書いている。2017年はおろか、もっと前からとっくの昔に、GNU/Linuxデスクトップの時代は到来しているし、ブログ執筆であろうとプレゼンのスライド資料作成であろうと、GNU/Linuxは十分実用に耐えうる。

Jim ZemlinにはよろしくLinuxデスクトップを使い自らドッグフードを食らってもらいたいところだ。

2017-09-12

江添ボドゲ会 9月17日

自宅でボドゲ会を9月17日に開催します。

江添ボドゲ会 9月17日 - connpass

2017-08-28

麻布十番で職務質問を受けた話

残暑も残る8月27日の日曜日のことであった。その日、私は知人のぽんこつさんが自宅でボードゲーム会を行うというので、昼からぽんこつさんの住んでいる麻布十番に出かけた。

ぽんこつボドゲVer17.08 - connpass

その日の私の出で立ちは、7月3日に受けた違法な職質のときと同じ、帽子、即乾シャツ、即乾アームカバー、デニム生地風ストレッチパンツ、半長靴であった。

本の虫: 警察官に職務質問をされた話

また、リュックの中にはボードゲームを満載し、かつボルダリングの道具も入れていた。これはぽんこつさんの自宅近くにスパイダーというクライミングジムがあり、ボドゲ会が終わった後に行こうと考えたためである。

約束の12時に間に合うよう、余裕を持って家を出たつもりであったが、待ち合わせ場所の麻布十番駅についたときにはすでに12時20分。ぽんこつさんの姿は見当たらない。

これはうっかり出遅れた。ぽんこつさんとボドゲ仲間達は今頃、どこかの飲食店で昼食を取っているに違いない。私は携帯電話を所有していないため、ぽんこつさんに連絡を取るのが不可能だ。しかし、私はぽんこつさんの自宅を知っている。単独で向かえばよかろう。そう判断した私は、道中のコンビニで軽食を買い求め、ひとりぽんこつ宅に向かった。

ところで、麻布十番というのはやや特殊な場所である。極めて地代が高く、およそ人の住む場所ではない。ぽんこつさんは職場がどこであれ、職場近くに住むという強い信念を持っている人だ。しかし、さすがに麻布十番という場所は、優秀なエンジニアである彼の少なからぬ給料から考えても、やや家賃が高いはずだ。第一周辺環境が人が住むのにまるで向いていない。例えば、麻布十番には安いフランチャイズ店 の牛丼屋がない。麻布十番という地代は牛丼屋で利益を見込めないからであろう。一方、マクドナルドはある。マクドナルドの価格帯からすると、麻布十番に出店するのは大赤字のはずだが、おそらくこれは「マクドナルドはどこにでもある」という雰囲気を出すための広告の目的も兼ねて出店しているのであろう。

また、麻布十番は、路上にやたらに警察官が警備に当たっている。これはどうも、麻布十番には諸外国の大使館が多いためらしい。また、当日は麻布十番で祭りが開かれているらしく、いつもに増して路上に立つ警察官の数が多かった。

さて、ぽんこつさんの自宅についたが、あいにくとインターホンに応答がない。どうやらぽんこつさんとそのボドゲ仲間たちは、まだ昼食に出かけているようだ。さてどうしよう。

すでに書いたように、私は携帯電話を持っていないので、ぽんこつさんと連絡が取れない。この場を離れると、ぽんこつさんと入れ違いになってしまう可能性がある。ぽんこつさんはせいぜいあと2,30分もすれば昼食から帰宅するはずである。すると、私の取るべき最適な行動は、ぽんこつさんの自宅近くの路上でぽんこつさんの帰宅を待つということになる。そこで私は、自宅近くの路上に座り込み、コンビニで買った軽食をつまみながらぽんこつさんの帰りを待っていた。あいにくと現場は民家と接客を伴わない何らかの事務所などしかなく、ぽんこつさんの自宅を視界に収めることができる喫茶店のたぐいは存在しなかったからだ。

そのまま10分か20分ほど軽食を使いながら待っていると、路上に立っていた警察官がこちらに歩いてきた。

「さきほどからここにとどまっていますが、ここで何をしているのですか」

この警察官は私が先日違法な職務質問を受けたかどで国賠訴訟を提訴した人物であるとは思いもよらないはずだ。私は吹き出しそうになるのをこらえながら答えた。

「人を待っています。私は携帯電話を持っていないもので連絡を取る手段がないのです」
「荷物の中身を見せてもらっていいですか」
「なるほど、この場合は妥当な理由があると私も認める状況ではあります。見せましょう。しかし・・・」

と、ここまでいいかけたところで、ぽんこつさんとボドゲ仲間たちが道の向こうからやってきた。彼らは私と警察官が話し合っているところから、状況を一瞬で察したらしく、爆笑しながらやってきた。

その後、路上とぽんこつさんの自宅に入ってからもしばらく、我々の爆笑が止まらなかったことはここに書くまでもないことだ。その後、我々はボードゲームを行い。解散後、私はクライミングジムに行って、そして帰宅してこれを書いている。

これで私の人生において職質を受けるのは4度目だ。今回の職質は、その文脈上、開始するにあたって妥当な理由があると私も認めざるを得ない。さりながら、やや気になる点がある。私が「しかし」に続けて警察官に言おうとしたが、仲間が来たために言いそびれたことだ。

職務質問の根拠法である警察官職務執行法は、停止させて質問ができると書いてある。所持品の捜索ができるとは書いていない。所持品の捜索は憲法35条が令状なくしては行えないと定義するものであって、通常ならば令状のない所持品の捜索は違憲である。

しかし、過去の判決により、職務質問に付随して令状なしの所持品の捜索は違憲ではないという判例が存在する。しかし、あくまで、「職務質問に付随」して行えるものであり、当初から所持品の捜索を目的として行えるものではない。

今回、警察官は私の所持品を捜索すべき理由を何も告げずして、単に「荷物の中身を見せろ」と言った。これは職務質問に付随して行ったものであろうか。職務質問に付随して行うと言うからには、質問の過程で所持品の中身を改めることによって犯罪の有無を明らかにできると判明した場合に行うべきだろう。今回の職務質問は、単に私が何をしているか質問し、その答えを聞いただけで、突如として何の脈絡もなく、理由もなく、「荷物を見せろ」と言ったのであって、果たしてこれが職務質問に付随したものであると言えるだろうか。

警察官職務執行法には令状なく所持品の捜索ができるとは書いていない。私が過去に四回受けた職質では、皆同様に何の脈絡もなく即座に所持品の検査を要求されている。本来ならば憲法35条に違反する令状なしの所持品の捜索がこのようにたやすく行われる現状はおかしいのではないか。

2017-08-19

LLVMがWindowsのデバッグ情報フォーマットのPDBをサポート

LLVM Project Blog: LLVM on Windows now supports PDB Debug Info

この数年、clangをWindowsでソフトウェア開発するための世界級のツールチェインにするために尽力してきた。このことについては、すでに何度も書いてきたことだ。LLVMは完全なABI互換を実現した(ただしバグ互換ではない)。互換性を実現するのが難しい分野にデバッグ情報があるが、この2年間で、LLVMは飛躍的な発展をとげた。とりあえず結論を先に書くとこうだ。WindowsでClangを使うと、PDBデバッグ情報が出せる。

背景:CodeView VS PDB

CodeViewは1980年台の中頃にMicrosoftによって考案されたデバッグ情報フォーマットだ。様々な理由で、他のデバッガーはDWARFという独立したフォーマットを開発し、これは標準化されて、多くのコンパイラーとプログラミング言語でサポートされている。CodeViewは、DWARFと同じく、ソースコード行とコードアドレスのマッピングと、プログラムが使う型とシンボルのレコード集である。デバッガーはこの情報を使って、関数名でブレイクポイントを設定したり、変数の値を表示したりする。ただし、CodeViewはあまりよくドキュメント化されていない。最新の公式なドキュメントは少なくとも20年前のものだ。レコードの中にはドキュメント化されているものと同じフォーマットのものもあるが、まだドキュメント化されていない後々の追加のレコードもある。

ここで重要なのが、CodeViewは単にレコード集だということだ。もしユーザーが、「Fooの値を表示してくれ」といったときどうなるだろうか。デバッガーはFooについてのレコードを検索する。そして物事は更に複雑になる。どの最適化が有効にされていたのか? コンパイラーのバージョンは?(これはコンパイラーのバージョンによって一部のABIの非互換があったり、極度に最適化されたコードからバックトレースを再現する際のヒントとして使ったり、スタックが破壊されているかどうかの確認に重要だ)。プログラムには大量のシンボルがある。どうやって遅いO(n)にならずにシンボルを検索すればいいのか? どうやってコードを僅かに変更した時にインクリメンタルリンクを実現してデバッグ情報の再生成を回避すればいいのだ? 文字列の重複を省いて空間を節約するにはどうすれば? ここでPDBが登場する。

PDB(Program Database)は、その名前通り、データベースだ。これにはCodeViewが含まれているが、CodeViewレコードを様々な方法でインデックス化するための様々なものが含まれている。これによって型やシンボルを名前やアドレスで検索するのを高速化している。発想としては入力ファイルに対する「テーブル」と同等であり、ユーザーはその存在を気にすることはないものの、Windowsにおけるデバッグを快適にするのに貢献している。しかし問題がある。CodeViewはある程度はドキュメント化されているのに対し、PDBはまったくドキュメント化されていない。しかもその構造は複雑だ。

お手上げだ(ホントか?)

数年前、LLVMは開発の方向性として、CodeViewとPDBを出力する望みを一切捨て去り、以下の2つに注力することにした。

  1. clang-clはWindowsでDWARFデバッグ情報を出力する
  2. LLDBをWindowsに移植してWindows ABIに対応させる。これはVisual StudioやWinDbgをDWARFに対応させるより遥かに簡単だ(そもそもそんなことが可能であればの話だが。Visual StudioとWinDbgの拡張機能を使って実装可能なのだろうか)

実際、私はすでにブログ記事でこのことを2年前に書いている。作業の結果、LLDBをWindowsに移植して簡単なデバッグをさせることはできるようになった。

残念ながら、PDBのサポートは必須であることが明らかになった。LLVMの目標はWindowsエコシステムに囚われた開発者にとってできるだけ抵抗が少なくなるようにすることである。Windows Performance AnalyzerやvTuneのようなツールはとても強力でエンジニアの慣れ親しんだものである。企業はPDBファイルを保存、収集してクラッシュダンプを解析するインフラに投資している。PDBによるデバッグはとても高速だ。というのも、インデックスはファイルフォーマットで実現されていて、デバッガーが起動時にシンボルをインデックス化しなくてもいいためだ。それに、WinDbgのようなツールはすでにデバッグ用途に便利で、率直に言って、多くの(おそらくはほとんどの)Windows開発者がVisual Studioを手放すためには、彼らの死体の手からもぎ取る必要があるだろう。

私がとりあえずMicrosoftに協力を求めてみればええんちゃうと提案したときには皆から冷たいまなざしを受けたものだ。しかし、最終的に我々はMicrosoftに協力を求めた、そしてMSは協力した。協力はMicrosoft Githubにコード片を投下するという形で得られた。後はこのコードを解析するだけだ。Microsoftが公開できたコード片はPDBのコードの一部(我々は推測と解析をしなければならないし、そもそもコードは半分ぐらいかけているのでコンパイルすら通らないわけだが)だけであるが、実装をするだけの情報は得られた。

このコードを1年半解析し、試し、更に解析し、更に試しなどした結果、lld(LLVMリンカー)はついに機能するPDBを出力することができるようになった。基本的なことであるコード行や名前でのブレイクポイントの設定や、変数の表示や、シンボルや型の検索は、すべて動くようになった(ただし、もちろん、バグ互換はない)

PDBの詳細を調べたい人のために我々はツールも開発中だ。llvm-pdbutilと呼ばれるツールで、Microsoftのcvdumpユーティリティとよく似たものだ。このツールはPDBの内部情報をダンプして、PDBとyamlの相互変換、2つのPDBのdiffなどを実現している。llvmpdbutilの簡単なドキュメントはここにある。PDBファイルフォーマットの詳細の解説はここにある。この2年間に我々が解析したすべてが書いてある(まだ途中だ。私はドキュメントとPDBの実装の両方に時間を割かなければならないのだ)

バグをもってこい!

さて、ここで読者の協力が必要となる。我々はPDBで簡単なデバッグ状況をテストしたが、まだデバッグ情報の品質としてはアルファ段階だと考えている。是非試して、問題をバグトラッカーで知らせてほしい。始めるためには、まず最新のWindows用Clangのスナップショットをダウンロードしよう。この機能をテストする簡単な2つの方法は以下だ。

  1. clang-clにlldを自動的に実行させる

    clang-cl -fuse-ld=lld -Z7 -MTd hello.cpp

  2. clang-clとlldを別々に実行する。

    clang-cl -c -Z7 -MTd -o hello.obj hello.cpp

    lld-link -debug hello.obj

バグレポートがあふれかえるのをお待ちしております!

Microsoftが我々に協力してgithubレポジトリにコードをアップロードしてくれたことに心から感謝している。Microsoftの協力なしには実現できなかったことだ。

ところで、将来期待される歓喜すべきある事柄について読者の想像に委ねたい。ここに書いたPDBサポートはWindows特有のAPIやdllやライブラリに一切依存していない。100%移植性がある。ところで、君はクロスコンパイルに興味があるかね?

Zach Turner(LLVMのWindowsチームとして)

なかなか興味深い。

ところで、Microsoftが公開したMicrosoft/microsoft-pdbはMSVCのPDBを処理しているコードの一部だ。PDBフォーマットの詳細を開示するよう要請したところ、コード片が開示され、しかも、Microsoft自ら、「ソースコードは究極のドキュメントである」"Source code is the ultimate documentation :-)"、書いているところを見ると、果たしてMicrosoft社内にPDBの詳細なドキュメントはあるのか疑問だ。

OracleがJava EE 8の開発をコミュニティの手に委ねたいとか言い出す

Opening Up Java EE | Oracle The Aquarium Blog

Oracleがブログで、Java EE 8の開発をコミュニティの手に委ねたいと表明している。その文章がいかにも回りくどく面白かったので、とりあえず翻訳してみた。

Java EE 8についてOracleは目覚ましい進展を続けてきた。規格はほぼ固まり、この夏にリファレンス実装を提供できる予定だ。Java EE 8の提供とJavaOne 2017カンファレンスが近づいてくるにつれ、OracleとしてはJava EEの開発をより変容する業界と技術要求に対してアジャイルかつレスポンシブに対応できる開発体制を再考する余地があるのではないかと考える。

Java EEは競争的な市場において、互換性の高い実装、業界に広く採用されている技術、多大な既存のフレームワークとツール、エンタープライズとエンドユーザーに対する数限りない適用例でもって、大変に成功している。しかし、Java EEはJava EEコミュニティも参加するオープンソースで開発されているとはいえ、その開発体制は十分にアジャイルでフレキシブルでオープンではなく、特に他のオープンソースコミュニティと比較すると違いが顕著である。Oracleはよりベターにやりたい。

Oracle内部ではjava EE 8提供後のJava EE開発体制をいかにして改善できるかについて議論している。Oracleとしてはリファレンス実装とテスト互換キットを含むJava EE技術をどこかのオープンソース財団に移行するのが、よりアジャイルな開発体制、よりフレキシブルなライセンスの実現、管理体制の変革という点で、適切な方法であると信ずる。OracleはJava EEの開発をこの方向ですすめるべく、この可能性をコミュニティと我々のライセンシーといくつかの財団に掛け合う予定だ。

Oracleは開発者、エンドユーザー、カスタマー、消費者、貢献者、パートナー、ライセンシーに対する貢献を続けていく。そしてOracleは既存のJava EE実装と将来のJava EE 8実装に対するサポートを続ける。Orackeは将来のJava EE技術の発展に関与し続ける。しかし、単一のベンダーやプラットフォームの意向によらないよりオープンな開発体制は、イノベーションの促進によろしく、コミュニティの最大の関心を引きつけるところであると信ずる。

この件に関してコメントしたい人は、feedback@javaee.groups.ioにメールしてもらいたい。この件の進展についての詳細を告知する。

この件がWebLogic Serverに与える影響については、こちらを参照。

お断り

以上はOracleの一般的なプロダクトの方向性を示すものです。以上は情報提供の目的で提示されたものであり、将来に渡って何らかの約束をするものではありません。以上は何らかの財産、コード、機能の提供を約束したものではなく、購入選択において考慮すべき情報ではありませんOracleのプロダクトの機能の開発、リリース、その提供時期はOracleが決定するものであります。

Oracleの過去の前科から考えると、この手のコミュニティに開発を委ねるという方法で、市場価値の薄れてきたSolarisを殺し、SPARCを殺し、Star Officeも殺してきた。要するに旧Sun Microsystemsの製品を続々と殺し続けてきたわけだ。Java EE 8も後に続くのだろうか。

ただ思うと、JVMには未だに価値を認める人間が多いのに対し、Javaはそれほど空かれていない。だからScalaとかKotlinとかその他多くのJVMで動く言語が流行っているわけだ。JVMはともかくJavaの将来性はあるのだろうか。

2017-08-16

江添ボドゲ会 8月20日

8月20日に自宅でボードゲーム会を開催します。詳細はconnpassで。

江添ボドゲ会 8月20日 - connpass

2017-08-04

C++17の参考書がだいぶ完成してきたので査読大募集中

半年前から書き始めたC++17の参考書がだいぶ完成してきた。参考書はGitHubで公開している。不備を発見したら、どんどんPRを投げてもらいたい。すでに28件のPRを処理した。

EzoeRyou/cpp17book: textbook for C++17

昨日書きあげたばかりのC++17で追加された数学用の特殊関数の章は特に数学とC++の両方に詳しい人間の検証を必要としている。

cpp17book/045-cpp17-lib-mathematical-special-functions.md at master · EzoeRyou/cpp17book

さて、残りは小粒なライブラリと、ファイルシステムだ。

C++17にはposixのファイルシステム操作をC++風にラップしたファイルシステムライブラリが入る。これを一体どうしたものか迷っている。

というのも、ファイルシステムライブラリは膨大で、その解説には100ページ以上かかる。果たしてそんな解説をして、これ以上執筆機関を伸ばし、またページを増やしてもいいものだろうか。

とはいえ、今C++の詳細な参考書はなかなか出版が減っているし、かつC++のファイルシステムライブラリだけで一冊の本が出るとも思えないので、書いておくべきだろうか。

この参考書が完成したら、アスキードワンゴから出版をすることを見込んでいる。

ドワンゴ広告

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

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

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

2017-07-24

濫用にあたる職務質問を受けたと考えたので弁護士と現場検証してきた

承前

本の虫: 警察官に職務質問をされた話

本の虫: 濫用に当たる職務質問を受けたと考えたので弁護士に相談して訴訟を起こすことになった話

さて、弁護士と職務質問を受けた現場にいって当時の流れを再現してきた。

ところで、私は今回の濫用に当たる職務質問を受けたことを弁護士に相談して、裁判費用と弁護士報酬を合わせて61万円を支払った。こう書くと、にわかにカンパを支払いたいという連絡が何件もやってきた。61万円は少ない額ではない。幸い、私には貯蓄と収入があるので、生活に影響を与える出費ではない。

この問題に身銭を切ってまで感心を寄せる人間がこれだけいるのだという可視化のためにカンパを受け取るというのも考えたが、現在、生活が困窮しているわけでもなく、またこれ以上の出費が見込まれるわけでもなく、かつ出所のわからない金をあまり受け取りたくはないというのもある。第一その金は61万の支出と相殺して所得はなかった扱いにしていいのかどうか、よくわからないところもある。

そこで、私は日頃から私がカンパしたいと思っているが、クレジットカードを持っていないために積極的にカンパしてこなかった団体へ誘導する形を取りたいと思う。私にカンパを送りたいと思うのであれば、私に直接送るかわりに、私がカンパを送りたいと思っている団体に直接カンパを送ればよい。そうすれば間接的に私にカンパを送ったことになるだろう。

賛助会員・カンパ募集中 - 明るい警察を実現する全国ネットワーク

これは今回、私が相談した弁護士が運営している団体で、その趣旨は警察官の働きやすい環境を作ることにあるのだそうだ。結局、末端の警察官というのは、公式には存在を認めていない職質ノルマにより、本来必要のない職質をしなければならない状況に晒されており、そういった警察官の置かれている状況を改善することが本来の目的なのだそうだ。

この団体への寄付は、シンポジウムの開催費用などに使われるそうだ。

Support the Free Software Foundation | Free Software Foundation

自由ソフトウェア財団は、RMSが創始し、GNUというOSを始めとした自由なソフトウェアの開発を行っている。私はGNUのソフトウェアの恩恵を受けている。

Donate | The Linux Foundation

Linux財団はLinuxカーネルに関わる啓蒙や標準化を行っている。私はLinuxカーネルの恩恵を受けている。

OpenBSD: Donations

OpenBSDはOpenSSHを開発している。私はOSとしてのOpenBSDは使っていないが、sshは毎日使っているので恩恵を受けている。

ウィキペディア創設者ジミー・ウェールズからのお願い

Wikipediaは、その情報の正確性は担保されていないものの、読み物として面白く、私も常日頃から恩恵を受けている。

sponsor Vim development : vim online

Vimというのは素晴らしい万人向けのテキストエディターであり、私も毎日使っている。したがって私はとてつもなく恩恵を受けている。このブログの文章もVimで書いている。もしVimがなければ私のテキスト入力作業の生産性は著しく下がるだろう。Vimはウガンダへの寄付を呼びかけている。

さて、まだ他にもカンパすべき団体はいくらでもいるのだが、今回はこのぐらいにしておこう。

2017-07-14

濫用に当たる職務質問を受けたと考えたので弁護士に相談して訴訟を起こすことになった話

去る7月3日の午後の通勤途中に、私は職務質問を受けた。その次第は以下のブログ記事に職務質問を受けた当日書いて投稿した。ただし、投稿時に日付を超えてしまったので投稿日時は7月4日になっている。

本の虫: 警察官に職務質問をされた話

さて、振り返って見るに、私は先日の職務質問が警察官職務執行法第一条に規定された、「目的のため必要な最小の限度」を超えていて、「濫用」にあたるのではないかと考える。というのも、

  1. 「下を向いて歩いていた」、「帽子を目深にかぶっていた」という理由は、同法二条にある「合理的に判断して何らかの犯罪を犯し、若しくは犯そうとしていると疑うに足りる相当な理由」にはならない。
  2. 仮に「疑うに足りる相当な理由」であったとしても、職務質問を開始してかなり早い段階で、その疑いに対して「重い荷物を背負って長距離を歩いたので疲れたのではないか」、「人間は下ぐらい向くものだ」、「日差しが強く帽子をかぶるのは当然だ」と回答しているので、疑いに対して合理的な理由を与え、職務質問は中止されるべきであった。
  3. 当日は事件が起きて容疑者が付近を逃走中といったような、特に集中して職務質問を行うべき緊急の理由もなかった。
  4. 当日の路上は通行人がそれほど多くなく、私は路上に止まっていても「交通の妨害」にはならなかったので、無人駐車場という私有地に移動させる根拠はなかった。
  5. 一時間以上も停止させて同じ質問をし、自発的に任意の所持品検査に応じない限り停止を解かないのは「必要な最小の限度」を超えている。

もちろん、これは私の常識の範囲内で判断したことであり、あるいは濫用にあたらない最小の限度かもしれず、またこの行為が適法な職務質問とするべき根拠となる法律や判例が存在するかもしれない。そこで私は、弁護士に相談をすることにした。

世の中に弁護士は大勢いるが、特に似たような事例で裁判を起こしているような弁護士のほうが、関連する法律や判例をすでに調べた経験もあり、適切な判断ができるだろうと考えた。

また過去の判例を調べると、2013年に秋葉原で職質を受けてビクトリノックスを押収されたという件で争った判例がある。この裁判を担当した弁護士であれば適任であろうと考え、調べたところ、「明るい警察を実現する全国ネットワーク」という団体の清水勉弁護士であることがわかったので、早速連絡を取ることにした。

FrontPage - 明るい警察を実現する全国ネットワーク

連絡を取ったところ、さくら通り法律事務所の相談料は30分につき5400円ということであったので、相談をしに行くことにした。

さて相談をしたところ、弁護士の意見では、今回の件は職質を始めること自体が違法であったということであった。つまり上記の1.の段階で私の判断が正しかったということになる。

さて、職務質問が違法である可能性が高いことを確認した上で、今後の行動を決定しなければならない。もし職務質問が違法であれば、私の権利が不当に侵害されたことになる。ましてや私は通勤途中に毎回1時間以上停止させられたくはない。弁護士と相談した上で今後私が取りうる行動としては、以下の選択肢がある。

  1. 何もしない
  2. 警察に対して違法な職務質問であったと話し合いをする
  3. 人権擁護委員会や弁護士会を通じて警察に違法な職務質問であったと話し合いをする
  4. 違法な職務質問を受けたので賠償を求めて訴訟を起こす

権利の上にあぐらをかいていても意味がなく、憲法に規定された国民に保障された自由と権利を不断の努力で保持するためにも、私は裁判を起こして判決を出すのが最も適切な行動であると判断したので、裁判を起こすことにした。

その場で弁護士に裁判を依頼した場合の費用を算出してもらったところ、裁判費用、裁判のためにかかる経費、弁護士への報酬を諸々合わせて、合計61万円であるという。今回の相談料は61万円の中に含まれるそうだ。不断の努力のためであれば、61万円は出してもよい額だ。また、事前に調べたところ、裁判を起こすのにかかる費用は5,60万円であるらしいので、61万円は相場通りの適正な額であろうと判断した。

そこで、裁判を依頼した。

ところで、弁護士に相談したところ、職務質問にまつわる証明しようのない話をいくつか聞くことができた。与太話として興味深い。

まず、職務質問にあいやすいのは、男で、スーツを着ておらず、大きなリュックを背負っている人間であるという。私の状況に偶然一致する。

私に職務質問をした警察官は3人組で、一人は若く、二人は中年であった。主に私と話をしたのは中年のうちの一人で、若い警察官も若干の話をした。残る中年の警察官とはほとんど話をしなかった。

弁護士の推測によれば、私は警察官による職務質問の練習台にされたのだということであった。若い警察官に職務質問を練習させるために往来で職務質問をさせる。私とよく話した方の中年警察官は職務質問を指導する立場にあり、ほとんど話をしなかった方の中年警察官は、指導を監督する立場にあったのではないかということであった。ただ、警察官が3人いるのは珍しいことで、通常は指導役と練習生の2人組であるという。OJTじゃあるまいし。

警察官は、皆申し合わせたように「お願い」とか「説得」という言葉を一貫して使った。これは職務質問の訓練マニュアルの存在を示唆するものであるが、実際、そのような訓練マニュアルは存在するだろうということであった。

警察官は「平時から犯罪を未然に防ぐため、こうして一日に5,60件の職質をしているわけです」と発言した。犯罪を犯しそうな怪しい人間が都合よく安定して一日あたり5,60人発見できるのは不思議で、これは職務質問のノルマの存在を示唆するものである。弁護士は職務質問ノルマが存在するのではないかと考えているが、警察はこれまでにノルマの存在を認めていないのだそうだ。

私は職質をされた後も、平日は同じ帽子、同じ服装、同じリュックを背負って同じ道を同じ歩き方で通勤のために徒歩で移動している。いまだに職務質問を再現できていないが、今回の件で私は警察に職務質問をすると面倒な相手として認識されたので、今後、職務質問はされにくいであろうということであった。

最後に、裁判は時間がかかるので続報はもう少し先の話になるだろう。弁護士によれば、1年から1年半はかかるとのことであった。

2017-07-13

江添ボドゲ会 7月16日

今月も7月16日の日曜日に自宅でボドゲ会をする。場所は木場で、詳細は以下の通りconnpassで募集している。

江添ボドゲ会 7月16日 - connpass

ボドゲを毎月していきたい。

2017-07-04

警察官に職務質問をされた話

とても日差しの暑い7月、木場の自宅から銀座にある職場まで5kmの道を、5kgはある荷物を背負って徒歩で通勤していた。その日の私の出で立ちは、日焼けを防止するための大きな帽子、OD色の即乾シャツ、クライミング用のジーンズ風ストレッチパンツ、半長靴であった。勝鬨橋を超えて自販機で飲み物を買うと、急に警察官が3人近寄ってきた。

警察官「ちょっといいですか」
私「何ですか」
警察官「荷物の中を確認させていただきたい」
私「嫌です」
警察官「なぜですか」
私「応じる義務がないからです」
警察官「危険なものが入っているのではないですか」
私「入っていません」
警察官「では見せて証明してください」
私「見せる義務はありません」

このような問答がしばらく繰り返された挙句、私は出社をしなければならないのでその場を離れようとした。すると、警察官は回り込んで私の往来を妨害してくるではないか。人の往来を妨害するのは刑法に定められた犯罪である。

私「私の往来を妨害しないでください。犯罪です」
警察官「妨害していない」
私「では通してください」
警察官「まだ職務質問の途中だ」
私「すでに応じました」
警察官「リュックの中身を確認していない」
私「私に見せる義務はありません」

警察官はなおも執拗に私の往来を妨害した。私は警察手帳を出して、名前と階級を明らかにするよう要求した。警察官はこの要求に答えなければならないと法律上定められている。

3人の警察官は即座に、それぞれ警察手帳を出した。3人の警察官は、私のメモによれば、渦乃博之、井口?労人、晝?石健のような名前だった気がする。私のメモは適当に書きなぐったので細部の漢字が曖昧だ。特に?の前の文字は怪しい。3人とも階級は巡査長であった。認識番号はメモしなかった。

警察官「我々も名前を明かしたのですから、あなたも身分を明かしてください」

確かにそれは一理ある。もとより私に身分を隠すつもりはない。そこで私は予備自衛官手帳を出した。警察官はそのようなものを見ることに慣れていないらしく、私を現職の自衛官だと誤認した。手帳の表に「予備自衛官手帳」と書いてあるのに不思議なことだ。私は誤解する警察官に現職ではなく予備であることを説明した。

警察官の私の往来を妨害する行為はなおも激しくなった。私は往来を妨害して正面を塞ぐ警察官に対して、迂回をしようとしたが、迂回した方向にも回られた。その際、警察官の一人が、「公妨だ」とか、「あ、拳銃に触った」などとわざとらしく声を上げた。警察官が私の往来を回り込み、身をもって執拗に妨害しなければ、私は警察官の体に触れることはなかったし、拳銃のホルスターに手が当たることもなかっただろう。私は公務執行妨害をする意図はなく、拳銃に触る意図もなかった。

やがて、パトカーが到着し、さらに追加で6,7人ぐらいの警察官に周りを厳しく囲まれることになった。そして、最終的には脇道にある無人駐車場という私有地に移動させられた。

警察官「あなたは道の真ん中で通行の邪魔になっているから移動しましょう」
私「あなたが私の往来を妨害するという犯罪をしなければ私が道の真ん中で止まることはないのですよ」
警察官「妨害していません」
私「では私はいまから道を進みたいのですが通してくれますね。あ、移動するのは億劫でしょうから私の方から迂回しましょうか」
警察官「リュックの中身を見せてくれればすぐに通します」
私「リュックの中身を私が見せなければならない法的根拠を示していただければすぐにお見せします」
警察官「さっきから何度も同じことを言っているではないですか」
私「同じことを言っているのはあなたです」

警察官は私の往来を妨害し続けたが、往来を妨害しているということは否定した。

警察官は皆、一貫して法律にはない用語を使った。

私「私の往来を妨害するのは犯罪です」
警察官「妨害していない。現在、説得中です」
私「説得とはなんですか。どういう法的根拠があるのですか」
警察官「お願いをしています」
私「お願いとはなんですか。どういう法的根拠があるのですか」

警察官は、法的根拠について答えることはなかった。それもそのはずで、法律には「説得」とか「お願い」とかいった文言が使われているはずがない。この、「説得」、「お願い」という言葉は、複数の警官が一貫して使っていたので、おそらく警察の職務質問の訓練マニュアルにでもあるのだろう。

警察官「君には受忍義務(じゅにんぎむ)がある」

はて、「受忍義務」とは何だろうか。法律用語のようにもきこえるが、私の知る用語ではない。しかし、私は警察官職務執行法の全文を読んだことがある。その私が思い出せない用語なのだから、おそらく法律用語ではないのだろう。

警察官職務執行法

私「受忍義務とはどのような法律や判例で定められていますか」
警察官「いや、法律とか判例はどうでもいい」
私「なんと、警察官が法律や判例をどうでもいいというのですか」
警察官「違う。本官に対してではない。君に対して言ったのだよ」
私「なんと、警察官が一般市民に対して法律や判例をどうでもいいというのですか」
警察官「そうじゃなくて」

「公妨」、「あ、拳銃を触った」に引き続き、とんでもない発言が出てきた。主語がどちらにあるにせよ、この警察官は法律や判例はどうでもいいそうだ。

私「受忍義務を定めた法律や判例を教えてください」
警察官「法律や判例ではなくて、職務執行を遂行するにあたり必要であるという解釈である」
私「解釈? 法律や判例ではなく」
警察官「そうだ」
私「法的根拠はないんですね」

警察官は、嘘をつかず、受忍義務に法的根拠があるとは言わなかった。捜査に必要であるという解釈だと主張した。

ちなみに、あとで調べたところ、受忍義務とは法律用語ではなく、また直接判例によって支持されている概念でもないようだ。警察は長年、この不文律の受忍義務というものが存在するという法律の解釈を主張している。

警察官「法的根拠は職務執行法第二条に基づいています」
私「ならば、その一条にある濫用をしてならないという条項も守っていただきたい」
警察官「濫用していません」
私「では私の往来を妨害しないでいただきたい」
警察官「妨害していません。説得しています」
私「説得は非法律用語です」

そして議論は堂々巡りを繰り返す。そもそも、なぜ私が職質を受けているのか。私を怪しむに足る納得できる理由があればもちろん自発的に協力してもよい。

私「なぜ私を職務質問しているのですか」
警察官「本官が怪しいと思ったからです」
私「現在、付近で事件が起きて容疑者が逃走中ですか。それでしたら納得の行く理由ですので持ち物検査にも協力します」
警察官「違います」

警察官は嘘をつくことができないという制約がある。少なくとも、法的根拠や現在発生中の事件について、嘘をつくことはできない。後々問題になるからだ。実際、警察官は用心深く、この点において嘘をつくことはなかった。法的根拠について答えられない場合は押し黙ったり話をそらした。

私「私のどういう兆候が怪しいと思ったのですか」
警察官「うつむいて、下を向いて歩いていた」
私「うつむいて下を歩くのは犯罪ですか」
警察官「違います」
私「犯罪者はうつむいて下を向いて歩きやすいものだという統計結果はありますか」
警察官「薬物中毒者はよくうつむいて下を向いて歩くものだ。本官は薬物中毒者を多数見てきた経験論から知っている。君とは社会経験が違うのだよ」
私「薬物中毒者ならば私も以前、シェアハウスに住んでいて何人も見たことがありますが、そういう傾向はありませんでしたね」
警察官「本官は何百人もの薬物中毒者を見ている。君がみた薬物中毒者はそうでなかっただけだ」

私はこの日差しの強い炎天下の中、5kgの荷物を背負って5kmの道のりを歩いてきたのだ。疲れてうつむきがちなのは仕方がないではないか。あるいはうつむいて歩くのは私の癖かもしれない。何にせよ、下を向いて歩いているだけで怪しいというのは、私の納得できる理由ではない。日本国民は下を向いて歩いてはならないという法はない。

警察官「君は帽子を目深にかぶっていて顔が見えなかった」
私「この強い日差しの中、帽子をかぶるのは当然でしょう」

この理由も、私が納得して自発的に持ち物検査に応ずるほどの怪しむに足る理由ではない。日本国民は帽子をかぶってはならないという法は極めて限定的な状況においてしかない。例えば衆議院規則と参議院規則には議場に入る議員は許可なく帽子をかぶってはならないと書かれているが、私は議員ではないし、ここは義場でもない。

警察官「警察官に職務質問をして大声を上げ、その場から逃げようとしたのは怪しい」
私「よく訓練された私のよりも背丈の高い男が3人がかりで私の体を掴み、往来を妨害するのであれば恐怖ぐらい感じるでしょう。それに私に応じる義務はありません」

これも私が怪しい理由として納得できない。

警察官「あなたも社会人で働いているのならばわかるでしょう。リュックの中身を見せてくれればすぐにでも行ってもらって構いませんよ」

法的根拠に基づかず往来を妨害し、義務ではない行為を行うまで拘束する警察官というのは私の社会人としての常識ではわからない。

警察官「なぜ持ち物を見せないのですか」
私「見せる義務がないからです」
警察官「見せると問題になるものがあるのではないですか」
私「ありません」
警察官「では見せて証明してください」
私「見せる義務はありません」
警察官「見せて問題のないものしか持っていないのならば、なぜ見せないのですか」

この質問をした警察官は、私のプライバシー権に対する理念(隠すものがないならば全て見せてもよいという論法はなぜ間違っているのか)、憲法論、はては日本国憲法は日本国民が不断の努力で守らなければならないとしているが、日本は国民に武器を持つ権利を認めていないので現行の法律はおかしい。私はアメリカ合衆国の修正憲法第二条にある規律ある民兵の条項に賛同するものである。しかし私は法律を守る善良な日本国民であるので現行の法律にはもちろん従っていて武器は持っていないなどという私の思想を延々と聞かされることになった。

警察官「あなたは今までに軽犯罪法で捕まったことはありますか」
私「ありません。ただし私は法律のすべてを暗記しているわけではないので過去に法律に抵触した行動をした可能性はあります。しかし、仮にそうであったとしても、私に犯罪を行う意図はなかった。なぜこのようなことを言うかと言うと、マイナスドライバーを持っていただけでピッキング用具として軽犯罪法で捕まった事例を知っているからだ。今、私のリュックの中にマイナスドライバーはおそらく入っていないはずだが、私は日常的にマイナスドライバーを使うのでひょっとしたら入っているかもしれない」
警察官「あなたの場合、マイナスドライバーは正当な理由があると認めます」
私「ペーパーナイフや尖った鉛筆などは」
警察官「それも正当な理由として認めます。ここにこれだけ警察官がいるのだから変なことはしません」
私「信じたいところですが、あなたはさっき、法律や判例はどうでもいいから、と言いましたね」
警察官「そうじゃない。ほら、この警官も帽子を脱いで頭を下げますから」
私「頭を下げたその警察官はさっき、公妨とか、あ、拳銃を触った、と言いましたね」

法律は無数にあり、すべての法律に抵触しないなどおよそ無理な話だ。例えば日本国政府は公共建築物等における木材の利用の促進に関する法律に常に違反し続けている。本来、木造でもよいはずの公共建築物を木造にしないことがあるのだから。

公共建築物等における木材の利用の促進に関する法律:林野庁

やがて、現場に追加でやってきた警官は去っていった。そして最初に私に職務質問をした3人の警官だけが残った。

パラノイアというTRPGのゲームがある。基本的には理不尽な圧迫面接をのらりくらりとかわしつづけるゲームなのだが、この今の取り調べはまさにパラノイアのセッションを彷彿とさせる。ただしパラノイアと違い、警察は嘘をつけない、警察は何時間でも私を路上に拘束し続けることができるのでセッションをやめられない、という制約はあるのだが。

さて、私は警察官職務執行法をすべて読んだことがあり、パラノイアのルールブックもすべて読んでいて、GM経験もあるので、このパラノイアのセッションのような不毛な議論(私の権利が不当に侵害されているので不毛ではないのだが)をいくらでも続けられるのだが、いい加減に職務執行法の一条を守って濫用をやめるか、自発的に捜査に協力するだけの納得できる理由を提示してほしいものだ。例えば、今ここで私がナイフを持っているのを見たと言ったのであれば私は自発的に捜査に協力するだろう。というのも、私はいかように悪意をもって解釈してもナイフだとは認定できないものしか持っていないのだから、ナイフを見たと信ずるに足る理由などあるわけがなく、真っ赤な嘘だとわかる。

しかし、警察官はよく訓練されていて注意深く嘘を避けていた。存在しない法的根拠を挙げることはない。何の法律や判例の支持もない受忍義務については解釈であると正しく答える。「法律や判例はどうでもいい」とぃうのは、およそ警察官にあるまじき発言ではあるが、意見であって嘘とか本当とかいった性質のものではないだろう。「あ、銃に触った」という発言は嘘ではないのかもしれない。ただし道を塞ぐ警察官を避けようと左に移動した私の往来を妨害する形で銃のホルスターをつけている右腰を私に押し付けたので、仮に私が銃を触ったとしても、それは私の意図ではないし私に責任はない。

嘘だと私が判断した発言は、「公妨だ」、「濫用していない」、「往来を妨害していない」ぐらいなものだろうか。

さて、駐車場という私有地に停止されての職務質問は2時間弱ほど続いた。警察官職務執行法に定められている濫用というのは、一体、何時間の停止からを言うのであろうか。

結局、最終的に警察官の提案した、リュックの上から触って調べることで怪しいものがないかどうか所持品検査を行うというのが、個人的に面白かったので、その方法で検査をさせることにした。

私「そんな方法で怪しいものがあるかどうかわかるものですかね」
警察官「私にはわかります。これはなんですか」
私「万年筆ですね」
警察官「あとで壊したとか言わないでくださいよ」
私「触っていいとは言いましたが、壊していいと言った覚えはありませんね」
警察官「これは何ですか」
私「メガネケースですね」
警察官「メガネケースの中に薬物を隠すというのはよくあることです。出して見せてもらっていいですか」
私「応じる義務はありませんね」
警察官「これは何ですか」
私「ラップトップですね」
警察官「ラップトップとはなんですか」
私「ノートPCとも呼ばれていますね」
警察官「これは何ですか」
私「ラップトップのケースですね」
警察官「ノートPCのケースがこんなに小さいものですか」
私「12.6インチでとても薄いラップトップです」
警察官「これは何ですか」
私「何でしょうねこれは。ああ、コンセントですね。ラップトップのACアダプターの」
警察官「とても重いリュックですね」
私「ラップトップ2台と周辺機器が入っていますからね」

そして開放された。

そういえば、私が人生で初めて職質をされたときは、神保町に行きたくて神田駅で降りたが、行き方がわからず、その近くの交番に大きな地図が見えたので、見るために入ったときであった。ちょうど秋葉原でナイフを振り回した事件の記憶もまだ浅い時期であった。

警察官「ちょっといいですか、荷物の検査をさせてください」
私「なぜですか」
警察官「最近物騒ですからね。ちょっと前も秋葉原でナイフを振り回す事件がおきましたし」
私「これから犯罪を犯そうという人間がわざわざ交番に立ち寄るのですか」
警察官「いえ、念のため・・・はい終わりました」
私「神保町へ行くための地図を見たかっただけなのに不思議だ」
警察官「なぜ早く言ってくれないのです。道は・・・」
私「地図さえ見れればそれでいいのです」