2016-06-29

C++標準化委員会の文書: P0250R0-P0259R0

P0250R1: Wording improvements for initialization and thread ids (CWG 2046)

実行単位と実行順序についての文面や言葉の使い分けを微妙に変える提案。

標準化委員会の中では、C++は将来的に、プログラムが明示的にスレッドを使っていなかったとしても、実装が自動的に初期化を並列実行することを許可したいコンセンサスがあるが、現行の文面も既存のコードもそのまま対応できるようにはなっていない。とりあえず文面を整理する。

[PDF] P0251R0: Unified Call Syntax Wording

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

f( x, y )という式を書いた時に、f( x, y )を満たすfが存在しない場合、x.f( y )を呼び出す機能のことだ。

template < typename T >
void f( T x, T y )
{
    compare( x, y ) ;
}

この例では、もしcompare( x, y )を満たすcompareが存在しない場合、x.compare( y )の呼び出しが試みられる。

当初の提案に上がっていた、x.f(y)をf(x,y)として扱う機能は省かれた。

これにより、ジェネリックコードは渡された型について気にする必要がなくなる。

[PDF] P0252R1: Operator Dot Wording

operator .をオーバーロード可能にする提案。operator .をオーバーロードした型に対するメンバーアクセスは、原則としてoperator .の戻り値に対して適用される。型に同じ名前のメンバー名がある場合を除く。

template < typename T >
class vector_ref
{
    std::vector<T> v ;
public :
    std::vector<T> & operator .() { return v ;}
    std::vector<T> const  & operator .() const { return v ;}

    std::size_t size() const { return 1 ; }
} ;

int main()
{
    vector_ref r ;

    // operator .を経由した
    // vector_ref.vに対する操作
    r.push_back(0) ;

    // vector_ref.sizeを呼ぶ
    r.size() ;
}

これにより、スマートリファレンスを実装することが可能になる。

operator .はクラス型から、リファレンス型を返すことができる。operator .をオーバーロードした型を、リファレンスサロゲート型と呼ぶ。複数のoperator .が記述されている場合、メンバー名によるオーバーロード解決が行われる。

struct A
{
    int x ;
} ;

struct B
{
    int y ;
}

struct C 
{
    A a ;
    B b ;
    A & operator .() { return a ; } 
    B & operator .() { return b ; }
} ;

int main()
{
    C c{ } ;

    c.x = 0 ; // c.a.x
    c.y = 0 ; // c.b.y
}

名前が衝突した場合は曖昧なためill-formedになる。

struct A
{
    int x ;
} ;

struct B
{
    int x ;
}

struct C 
{
    A a ;
    B b ;
    A & operator .() { return a ; } 
    B & operator .() { return b ; }
} ;

int main()
{
    C c{ } ;

    c.x = 0 ; // エラー、曖昧
}

リファレンスサロゲート型によって初期化した場合、オーバーロード解決により最適なoperator .が選ばれる

struct X
{
    int i ;
    double d ;

    int & operator . () { return i ; }
    double & operator . () { return d ; }
} ;

このようなリファレンスサロゲート型に対して、

以下はwell-formedとなる。

X x{ 0, 0.0 } ;
int i = x ; // well-formed
double d = x ; // well-formed

リファレンスサロゲート型に対する代入には、そのようなオーバーロード解決が働かず、operator .も使っていないため、以下はill-formedとなるのか、それともコピー代入演算子の呼び出しもoperator .を使うからwell-formedなのか、よくわからない。


X x{ 0, 0.0 } ;
x = 0 ; // 謎
x = 0.0 ; // 謎

また、operator .と変換関数がある場合、変換関数が優先されるのではないかと思われる。

struct X
{
    int i ;
    int & operator . () { return i ; }
    operator int & () { return i ; }
} ;

X x{0} ;
int i = x ; // call conversion function

と、このようないろいろな疑問を論文著者に聞いてみたところ、実際オーバーロード解決についてあやふやなため、いま開催中のOulu会議で文書自体が却下されたらしい。

[PDF] P0253R1: Fixing a design mistake in the searchers interface in Library Fundamentals

BMサーチなどを実装するために設計されたsearcherの戻り値を、パターンにマッチした先頭へのイテレーターを返すのではなく、マッチしたパターンの先頭と末尾のイテレーターのpairを返すようにする提案。

次のパターンを探したいことがよくあるから最適化のため。

[PDF] P0254R1: Integrating std::string_view and std::string

stringからstring_viewへの変換は、stringの変換関数が担うべきであるため、そのように設計を変更する提案。

[PDF] P0255R0: C++ Static Reflection via template pack expansion

テンプレートのパック展開を用いた静的リフレクション。使いたくないほど文法が汚い。1

[PDF] P0256R0: C++ Reflection Light

現在提案されているC++の静的リフレクション機能を比較して考察している。

T型のデータメンバーのポインターを取得する

N4428提案

int size = std::class_traits<T>::class_members::size;
// テンプレートメタプログラミングにより0からsize-1までのそれぞれのIについて取得する
auto pointer = std::class_traits<C>::class_members::ge<I>::pointer;
// その後、pointerの型をそれぞれ調べて、データメンバーのみを抽出する処理が必要

P0194R0提案

typedef reflexpr(T) meta_T;
typedef std::meta::get_all_data_members_t<meta_T> meta_DMs;
int size = std::meta::get_size_v<meta_DMs>; // get number of data members
// apply template meta to recurrently pick each I, from 0 to size - 1
// テンプレートメタプログラミングにより、0からsize-1までのそれぞれのIについて取得する
typedef std::meta::get_element_t<meta_DMs, I> meta_F;
gauto pointer = std::meta::get_pointer_v<meta_F>;

P0255R0提案

auto pointers = std::make_tuple( typedef< T, is_member_object_pointer >... );

お題:プライベート・ライアンは救えるか?

struct X {
private:
    int ryan;
};

Urbana会議の結論として、privateメンバーにはうっかりアクセスできないようにしたい。既存のコードにアクセス性を与えるような変更ができないようにしたい。reflection_unsafeのように明示的な操作を必要とするようにすべきか。

[PDF] P0257R1: A byte type for increased type safety

1バイトを表現するstd::byte型を標準ライブラリに追加する提案。

現在、1バイトを表現するには、char, signed char, unsigned charが使われているが、char型には、バイト単位のアクセス、数値型、文字型という3つの目的が割り当てられており、混同しやすい。そのため、バイト単位のアクセス専門の型が必要だ。

std::byteは以下のようにscoped enumで定義されている。


namespace std {
    enum class byte : unsigned char { } ;
}

わざわざコア言語に新しいキーワードとして組み込むまでもなく、既存の言語機能だけで実現できるとしている。

また、コア言語に手を加えて、今までのvoid *からchar *に加えて、std::byte *にstatic_castした場合でもバイト単位でのアクセスが保証される。

P0258R1: is_contiguous_layout

is_contiguous_layout traitsの追加。型がstandard layout typeかつ、すべてのビットがオブジェクトの値の表現に使われる場合にtrueを返す。

例えば、パディングビットが存在するような型に対してはfalseが返される。

目的は、バイト列からハッシュ計算をする最適化ができる型かどうか判定するためだ。

[PDF] P0259R0: fixed_string: a compile-time string

constexpr実装できるbasic_fixed_stringの提案。

basic_stringはconstexpr実装できないので、コンパイル時に文字列処理をするためにconstexpr実装できる設計の文字列クラスを追加する。

constexpr auto hello = std::make_fixed_string("hello") ;
constexpr auto world = std::make_fixed_string("world") ;

constexpr auto helloworld = hello + ", " + world ;

static_assert( helloworld == "hello, world" ) ;

ドワンゴ広告

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

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

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

2016-06-28

C++標準化委員会の文書: P0240R0-P0249R0

P0240R0: Why I want Concepts, but why they should come later rather than sooner

P0225R0「何故私はコンセプトをすぐに欲しているのか」に対する反論、「何故私はコンセプトを欲しているが、時期尚早であるのか」と題された文書。

現在のコンセプトの問題は、標準ライブラリがまだコンセプトに対応していないことと、constrained templateのチェックができないことだ。

標準ライブラリはプログラマーの模範となるべきライブラリで、標準ライブラリですら対応できていない言語機能は、有用性が十分に検証されているとは言えない。また、コンセプトの標準ライブラリがないということは、ユーザーごとに基本的なコンセプトですら、非互換な車輪の再発明が行われるので好ましくない。

現在のコンセプトは、contrained templateに対するチェック機能がない。つまり、テンプレートが、指定したコンセプトの要件のみを使っているコードかどうかを、実体化せずにチェックできない。C++0x時代のコンセプトを実装したConceptGCCの経験から言えば、エキスパートであっても、手で要件を全て網羅することはできず、コンパイラーに指摘されるまで気が付かない要件漏れが発生している。この機能なしではコンセプトは使い物にならない。また、現在提案中のコンセプトは、将来の拡張性の低い設計で、将来的にチェック機能を追加する際は、未チェックのコンセプトとチェックされるコンセプトという、2種類の言語機能を入れなければならず、言語機能が分断してしまう。

P0241R0: Remove Future-Related Explicit Specializations for Void

futureとpromiseのvoid型への特殊化を除去する提案。

P0146R1で、void型は完全型になるので、特殊化は不要になる。

P0242R0: Standard Library Support for Void

標準ライブラリ、特にiostreamをvoid型に対応させる提案。

P0146R0でvoidが完全型になるので、void型に対応する必要がある。

例えば、テンプレート引数でvoid型が渡された場合、テンプレートコードはコンパイル時分岐が必要なくなる。

template < typename F >
void call_print( F f )
{
    std::cout << f() << std::endl ;
}

int main()
{
    call_print( []{} ) ;
}

提案では、void型に対する入出力は、何もしないとしている。"void"を読み書きしたりするのは、既存のコードから考えても、余計なお世話であろうとしている。

P0244R1: Text_view: A C++ concepts and range based character encoding and code point enumeration library

UTF-8/UTF-16をコードポイント単位で読めるイテレーターを提供するtext_viewライブラリの提案

using CT = utf8_encoding::character_type;
auto tv = make_text_view<utf8_encoding>(u8"J\u00F8erg");
auto it = tv.begin();
assert(*it++ == CT{0x004A}); // 'J'
assert(*it++ == CT{0x00F8}); // 'ø'
assert(*it++ == CT{0x0065}); // 'e'

U+00F8は、UTF-8でエンコードすると、0xc30'b8になってしまうのだが、コードポイント単位でのイテレーター経由で見ることができる。

tahonermann/text_view: A C++ concepts and range based character encoding and code point enumeration library

実装はGitHubで公開されているが、コンセプト機能を多用しているため、最新の開発版GCCでしか動かない。

P0245R1: Hexadecimal floating literals for C++

16進数浮動小数点数リテラルの提案

int main()
{

    double d = 0xffp0 ;

    // 255.0000, 0x1.fep7
    printf("%f, %a\n", d, d ) ;
}

文法は、プレフィクス0x/0Xに続いて、16進数桁を記述して、.で区切って小数点以下を記述し、その後に2進数指数部を記述する。

16進数浮動小数点数リテラルには2進数exponentの指定が必須だ。2進数exponentはeではなくpで記述する

\[0xApB = A \times 2^B\]

たとえば、0xabcp3は、\(\texttt{0xabc} \times 2^3\)となる。

すでにC言語には入っている。

これを執筆途中に、トークン列のパースの問題に苦しんだ。

本の虫: C/C++で0xf+1は合法なのに0xe+1はコンパイルエラーになるのはなんで?

[PDF] P0246R0:Contract Assert Support Merged Proposal

フォントにLinux Libertineを使っているためstやctやらがligatureで表示されてやや戸惑う。

それはともかく、内容はcontract機能の議論の結果の改定案。contract機能とは、関数にpreconditionやpostconditionとして期待される状態をチェックするコードを記述できる機能で、コンパイル時や実行時にチェックできる。いわば高級なコア言語でサポートされたassertと言える。

[PDF] P0247R0: Criteria for Contract Support

これもLinux Libertineフォントによるligatureがうっとおしい。

内容は、実行時contractチェックが満たすべき要件について。

[PDF] P0248R0: Concepts in C++17

C++17にConceptが入るべきだと主張する文書。

筆者は現行のコンセプトに満足していない。

[PDF] P0249R0: Input Devices For 2D Graphics

イベント処理と割り込み処理のためのライブラリの提案。

BoostのSignalを参照している。また、QtやAllegro(ゲームフレームワーク)も引き合いに出しているほか、jQueryの手軽さに最も影響を受けた設計だとしている。

確かに、ある程度のGUIライブラリでは常に再発明されている機能ではあるが、皆が納得する設計にするのは難しい気がする。

ドワンゴ広告

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

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

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

2016-06-27

C/C++で0xf+1は合法なのに0xe+1はコンパイルエラーになるのはなんで?

以下のコードはwell-formedである。

int x = 0xf+1 ;

以下のコードはill-formedである。

int x = 0xe+1 ;

何故か。

理由は、0xf+1は、0xf, +, 1という3つのトークンとして認識されるが、0xe+1は、一つのpp-numberトークンとして認識されるためだ。これには、浮動小数点数リテラルの指数の文法が影響している。

具体的には、"数値 e 符号"という組み合わせの文字列が引っかかる。

そのため、16進数のeに1を加えた数を表現する場合は、eと+の間に空白を開けなければならない

int x = 0xe +1 ;

-の場合も同様。

ドワンゴ広告

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

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

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

2016-06-24

C++標準化委員会の文書: P0230R0-P0239R0

[PDF] P0230R0: SG14 Games Dev/Low Latency/Financial Meeting Minutes 2015/10/14-2015/02/10

ゲーム開発、低レイテンシー、Financialな業界からC++に提案をする会議の議事録。

[PDF] P0231R0: Extending the Transactional Memory Technical Specification to Support Commit Actions

トランザクショナルメモリーにコミット操作を追加する提案。コミット処理の結果が反映されるのはは、処理が終わったあとまで遅延される。

[PDF] P0232R0: A Concurrency ToolKit for Structured Deferral/Optimistic Speculation

RCUとハザードポインターの特性を面白い喩え話を用いて説明している。

シュレディンガーは動物園を持っている。動物園には様々な動物がいる。シュレディンガーは動物たちを管理するメモリ内データベースを持っている。動物の出産や購入はデータベースへの追加、死亡や売却はデータベースへの削除として操作される。動物にはネズミや昆虫も含まれるので、このデータベースは頻繁に更新される。このデータベースに対して、動物の状態を調べるためにクエリーすることができる。ただし、猫に対するクエリーが常に多い状態になっている。これは、おそらく動物園内のネズミが点滴の情報を調べるためにクエリーしているのだろうとシュレディンガーは推測している。

この頻繁に更新され、一部の情報に高頻度のクエリーが飛ぶ利用特性を持つデータベースの実装として、グローバルロック、バケットごとのロック、RCU、ハザードポインターによる実装を比較して、それぞれの特性を示している。

また、文書ではリファレンスカウントもRCUやハザードポインターと似たような特性を持つだろうとしている。

将来的には、C++にRCUやハザードポインターのライブラリを追加したいそうだ。

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

ハザードポインターの解説文書。

[PDF] P0234R0: Towards Massive Parallelism(aka Heterogeneous Devices/Accelerators/GPGPU) support in C++

GPGPUのような大規模な並列処理を行う異なるアーキテクチャが混在したコンピューター環境をC++でサポートするにあたって、現状の提案の一覧や、既存の実装を解説している。

[PDF] P0235R0: A Packaging System for C++

ブリザードエンタテイメント社によるC++のためのパッケージシステムの提案。

パッケージシステムというのは、Pythonにおけるpipや、Rubyにおけるgemや、node.jsにおけるnpmのような仕組みのことだ。ソフトウェアのライブラリを手軽に配布、入手、インストール、使用できるためのシステムのことだ。

提案はディレクトリ構造にまで言及するなど、かなり具体的なものになっている。

筆者の意見では、パッケージシステムはOSが提供するものであって、言語がそれぞれ提供するのは間違っている気がする。しかし、成功しているプログラミング言語はだいたいパッケージシステムを持っているのも事実だ。

文書の提案する仕組みに基づいたパッケージシステムをClangに実装したものが、ブリザードのGitHubで公開されている

https://github.com/Blizzard/clang

[PDF] P0236R0: Khronos's OpenCL SYCL to support Heterogeneous Devices for C++

OpenCL SYCLとしてC++によるOpenCLのラッパー規格の紹介。

[PDF] P0237R0: On the standardization of fundamental bit manipulation utilities

unsigned charの配列をビット列のコンテナーとして扱えるラッパークラスの提案。ビットに対するリファレンス、ポインター、イテレーターを提供している。

これにより、例えば立っているビットの数を数えたいときは、イテレーターをstd::countに渡せばよい。std::countは、std::bit_iteratorに対して、アーキテクチャがサポートしていれば、popcntを呼び出すなどの最適化も行える。

P0238R0: Return type deduction and SFINAE

戻り値の型の型推定に失敗した場合、ハードエラーではなくSFINAEにする提案。

[PDF] P0239R0: valueless_by_exception

variantのcorrupted_by_exceptionをvalueless_by_exceptionに改名する提案。

ドワンゴ広告

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

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

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

2016-06-21

Chrome 51のV8の興味深いバグ

以下のコードを実行した結果を予想してみてほしい。


function foo()
{
    return typeof null === "undefined" ;
}

for ( var i = 0 ; i < 1000 ; ++i )
{
    console.log( foo() ) ;
}

typeof nullの結果は"object"なので、"undefined"と===で比較するとfalseになる。したがって、関数fooは必ずfalseを返すはずである。1000回実行しようと常にfalseを返す関数は常にfalseを返すはずである。

では実際に実行して確かめてみよう。

コンソールにコピペするのとは挙動が違うが、何度もクリックすると、なぜかtrueを返すようになる。おそらく、コンソールにコピペすると毎回JITが走るので、挙動が違うのだろう。

ちなみに、workaroundとしては、typeof null === undefinedとかtypeof null === "undefined" + ""などがあるらしい。

参考

Javascript developers, be warned about this crazy JIT bug in V8!

Issue 604033 - chromium - JIT compiler not preserving method behavior - Monorail

ドワンゴ広告

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

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

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

C++標準化委員会の文書: P0220R0-P0229R0

P0220R1: Adopt Library Fundamentals V1 TS Components for C++17 (R1)

Library Fundamentals V1の規格への取り込み

Library Fundamentasについては、先日の勉強会資料でまとめている。

EzoeRyou/cpp17lib-slide: 勉強会のスライド資料

P0221R1: Proposed wording for default comparisons, revision 3

デフォルトの比較演算子を生成する提案。

デフォルトの比較演算子の挙動については、すでに解説してきた。現在問題になっているのは、スライシングだ。例えば以下の例をみてみよう。


struct B { int state ; } ;
struct D : B { int state ; }

void f()
{
    B b ;
    D d ;
    b < d ; // well-formed
}

b<dはwell-formedになる。なぜならば、オブジェクトdは、基本クラスBのサブオブジェクトへのリファレンスに、暗黙に変換されるからだ。つまり、上のコードは以下の意味を持つ。


b < static_cast< const B & >( d ) ;

この提案では、このスライシングを禁止する破壊的変更を伴う提案をしている。

提案はこうだ。コピーコンストラクター、operator =、比較関数、不等号関数に、クラスBから派生しているクラスDにたいして、const B &への暗黙の変換を禁止する。

その結果、上記のような合法なC++14コードはill-formedになる。

P0222R0: Allowing Anonymous Structs as Return Values

無名クラス型を関数の戻り値の型として返せる提案。

struct { int x, int y }
f()
{ return { 1, 2 } ; }

void g()
{
    auto [x, y] = f() ;
}

P0223R0: Class Namespace

クラスのメンバーをクラスの定義外で定義するときに、名前空間のようにクラススコープの中に入れることで、冗長な記述を省略できる文法の提案。

以下のようなクラスがあるとする

template < typename CharType, typename Traits, typename Allocator >
class MyString
{
    MyString( ) ;
} ;

クラスのメンバーをクラスの定義内で定義すると、クラス定義が極めて長くなってしまい。クラスの概要がつかみにくくなる。そのため、メンバーはクラスの定義外で定義したい。問題は、現状では極めて冗長な記述をしなければならない。

template < typename CharType, typename Traits, typename Allocator >
MyString< CharType, Traits, Allocator >::MyString( )
{
// ...
}

まずテンプレートを書いた上で、クラス名をテンプレートまで指定したスコープ解決演算子を書かなければならない。しかも、これをメンバー全てに対して記述する必要がある。

このような記述をするのは面倒だし、間違いのもとであるし、リファクタリングの妨げにもなる。そこで、以下のようにクラススコープを名前空間スコープのように使える文法を提案している。


template < typename CharType, typename Traits, typename Allocator >
namespace class MyString
{
    // 何も書かなくていい
    MyString()
    {
    // ...
    }
}

virtualやstaticはクラス名前空間では書けない。これは、現状でもクラス定義外では書けないからだ。

struct S
{
    virtual void f() ;
} ;

// virtualは書けない
void S::f() { }

P0224: Implicit Return Type

関数の戻り値の型を、先行する宣言から保管する提案。

int f() ;

// well-formed
// 戻り値の型はint
auto f() ;

C++14では、宣言が異なるためオーバーロード関数であるとみなされるが、引数が同じなのでill-formedになる。関数の戻り値の型でだけの違いではオーバーロード可能ではないので、不必要な制限である。

この制限緩和は、無名クラスを関数の戻り値の型として使えるようにするためである。


struct { int x, int y ; } f() ;

// OK
auto f()
{
    return { 1, 2 } ;
}

P0225R0: Why I want Concepts, and why I want them sooner rather than later

Ville Voutilainenによる、なぜConceptをC++17に入れるべきかという文書。

筆者の意見では、現状のConceptはC++17に入れるべきではない。

[PDF] P0226R1: Mathematical Special Functions for C++17, v5

数学関数をC++に追加する提案。

[PDF] P0227R0: Weakening the iterator categories of some standard algorithms

std::sort, std::inplace_merge, std::stable_sortのイテレーター要求をRandom Access IteratorからForward Iteratorに変更する提案。

アルゴリズムの研究の発展により、Forward Iteratorでもこれらのアルゴリズムをそれなりの効率で実装できるため。

[PDF] P0228R0: A Proposal to Add Safe Integer Types to the Standard Library Technical Report

数学的に正しく振る舞うかチェックできるライブラリ、std::safe<T>の提案

C++の組み込みの整数型は、数学の法則に正しく従わない。コンピューターの内部の挙動に従うように設計されている。これにより、以下のような数学的に正しいコードは、実際には正しく動作しない。

int f( int x )
{
    return x*x ;
}

なぜならば、x*xの結果は、int型で表現できる範囲を超えてしまうかもしれないからだ。

std::safe<T>は、整数型Tを置き換えて使うことができる。もし、結果が数学的に正しくない場合、例外が投げられる。

int f( std::safe<int> x )
{
    return x*x ;
}

ライブラリ実装により、実行時のオーバーヘッドを極力発生させないことができる。例えば以下のコード

int f( std::safe<std::int8_t> x )
{
    reutrn x*x ;
}

Integral promotionにより、x*xの結果の型はint型であり、それをint型として返す。int型はint8_t型同士の乗算結果を必ず数学的に正しく表現できるので、この場合に実行時チェックは必要ない。ライブラリの実装によって、そのような実行時チェックは省ける。

また、アーキテクチャによっては、演算結果が数学的に正しいかどうかをチェックできる機能を提供していることがあり、ライブラリがそのような機能を活用すれば、実行時のパフォーマンス向上に繋がる。

このライブラリは、整数型のDrop-in replacementとして使えることを目的としているため、追加のオプションなどはない。既存の似たようなライブラリには、オーバーフローやアンダーフローを検出するかどうかや、整数の範囲などを細かく指定できるものがある。このライブラリでは、単純性のため、そのような設計はしない。

なかなかいいライブラリだ。

[PDF] P0229R0: SG5 Transactional Memory Meeting minutes 2015/11/02-2016/02/08

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

ドワンゴ広告

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

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

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

2016-06-17

GNU/Linux版Steamがクソすぎる件

正確に言うと、Steam Runtimeがクソすぎる。

GNU/Linux版のSteamは、ユーザースペースをごっそり自前で用意している。これはSteam Runtimeと呼ばれている。steamランチャーとsteamのゲームは、Steam Runtimeでchrootされた環境で実行される。

GNU/Linuxにおいてプログラムをバイナリブロブで配布して実行する場合、ユーザースペースをすべて同梱した上でchrootして実行するのは手っ取り早く互換性を保てる方法だ。問題は、バイナリはそのまま時代に遅れていくということだ。

現在のSteam Runtimeは、Ubuntu 12.04のユーザースペースのものである。実に4年も前のバイナリを使っているわけだ。

事の発端は、GNU/Linuxで動かすfactorioのFPSが安定しないということだった。私が構築したゲーム用のGNU/Linux環境は、GeForce GTX670MXを使っている。数世代前のGPUとはいえ、factorioを動かすのに問題があるとは思えない。

STEAM_RUNTIME=0することで、steamランタイムを無効化できるのだが、依存するi386版のshared libraryを全部インストールしても、まだvgui2_s.soが見つからず起動できない。これはsteam側のshared libraryのようだ。

ところで、factorioの公式サイトのアカウントは、factorioを購入済みのSteamアカウントと紐付けることで、factorioのSteam DRMのかかっていないバイナリを落とすことができる。このバイナリで試してみたところ、なんとFPSが60で安定した。

結論、GNU/Linux版Steamはクソ

2016-06-16

C++標準化委員会の文書: P0210R0-P0219R0

P0210R0: A light-weight, compact dynamic array

軽量な動的配列ライブラリの提案。

vectorはamortized constant timeを実現するために、実際に必要なサイズよりも大きなサイズのメモリを確保している。これはメモリ消費量を必要以上に上げる。

そのため、そのような挙動を行わない軽量な動的配列ライブラリの追加をする提案。

このライブラリは、insert, push_back, emplace{,_back}, eraseといったメンバー関数は提供しない。これらのメンバー関数は、汎用的なコンテナーの要件には定められておらず、特定のコンテナーがそのような操作を効率的に実装できる場合にのみ提供されるものだからだ。

reserveやcapacityもない。

resize(n)は要素数をnにする再確保を常に行う(ただしn == size()の場合を除く)

このライブラリの名前をどうするかは自転車小屋の議論が続いている。

このライブラリはスタックからメモリを確保するdynarrayとは別の目的なので、別のライブラリとなる。

用途は、new T[n]の置き換えだ。

new T[n]にくらべて何が優れているのか。

  • サイズも一緒に管理される
  • クラスによってメモリが所有されるので、オブジェクトの破棄時にメモリも解放される
  • 要素に対して個々に破棄することができる

P0211R0: Allocator-aware library wrappers for dynamic allocation

アロケーターを使ってnew/make_unique/make_shared相当のことができるライブラリ。

new/make_unique/make_sharedは、operator newから生のストレージを確保して、オブジェクトを構築する。アロケーターでやるには、placement newでオブジェクトの構築を自前でやらなければならない。

auto p = new T( args ... ) ;
delete p ;

相当のことを、メモリ確保をアロケーターに変えて行いたい。このライブラリを使えば、以下のように書くことができる。

auto p = std::allocate_new<T>( alloc, args ... ) ;
std::allocate_delete( alloc, p ) ;

同様に、make_uniqueやmake_sharedも、以下のように書ける。

auto p = std::allocate_unique<T>( args ... ) ;
auto p = std::allocate_shared<T>( args ... ) ;

便利なライブラリだ。

P0212R0: Wording for [[maybe_unused]] attribute.

名前が使われないことをヒントとして示す[[maybe_unused]]の文面案。以前は[[unused]]だったが、改名された。

たとえば、以下の例でassertはプリプロセッサーマクロで、リリースビルドで消えてしまうので、コンパイラーからはresultが使用されていないように見え、変数が使われていないという警告を出すかもしれない。これをmaybe_unusedで解消できる。

int f(int x, int y)
{
    [[maybe_unused]] int result = error_check( x, y ) ;

    assert( result ) ;

    return do_something( x, y ) ;
}

P0213R0: Reexamining the Performance of Memory-Allocation Strategies

Fundamentals TSで追加される新しいメモリアロケーターのベンチマークテスト。

monotonicとは、メモリ解放をしないアロケーター。アロケーターオブジェクトの破棄時に、一括してメモリを解放する。メモリの中にリスト構造か何かをつくって開いている領域を探してといったメモリ管理が不要になるシンプルなデザイン

multipoolとは、確保する小さなサイズごとにテーブルを作りそこから確保する戦略のアロケーター

P0214R0: Data-Parallel Vector Types & Operations

1

ベクトル型を利用したSIMDプログラミングの説明

これ事態は提案ではなく、このような機能をC++に入れるにあたって委2員に基礎的な知識を説明するための文書とみえるが、それでも結構詳しく定義されている。

P0215R0: A Civil-Time Library

時間を、absolute time/civil time/time zoneに分類した上で、civil timeをサポートするライブラリの提案。

absolute timeとは、起点時間からのカウント数で、例えばtime_tなどが相当する。C++ではすでにchronoライブラリがある。

civil timeとは、グレゴリオ暦による年月日時分秒のことだ。これをサポートするライブラリを提案している。

タイムゾーンやサマータイムは含まれない。うるう秒も予測不可能なので含まれない。オブジェクトは時間は常に妥当な日付を指す。妥当でない日付を指定すると、正規化が行われる。例えば、1月32日を指定すると、2月1日になる。これにより、呼び出し側は範囲チェックを行わずに単純に日付同士の演算ができる。秒以下の時間は管理しない。

月同士の演算をする場合には、日を1日に合わせなければならない。

P0126R0:A Time-Zone Library

タイムゾーンライブラリの提案。

P0217R0: Wording for structured bindings

P0217R1: Wording for structured bindings

P0217R2: Wording for structured bindings

構造化束縛(structured bindings)の文面案。

多値を受け取る文法の提案。

publicな直接の非staticデータメンバーを持つクラス、配列、std::tuple, std::pairから、それぞれの要素の型と値で変数を初期化できる文法となっている。

int a[3] = { 1, 2, 3 } ;
// int, int, int
auto [ a1, a2, a3 ] = a ;

struct B { int x, double y, std::string z} ;
B b = { 1, 2.0, "3"} ;
// int, double, std::string
auto [ b1, b2, b3 ] = b ;

std::tuple< int, int, int > c{ 1, 2, 3 } ;
// int, int, int
auto [ c1, c2, c3 ] = c ;

これにより、多値を返す関数を使うのが楽になる。

std::tuple< int, double, std::string > f()
{
    return { 1, 2.0, "3" } ;
}

int g()
{
    auto [ x, y, z] = f() ;
}

文法は以下の通り。

auto [ identifier-list ] brace-or-equal-initializer

identifier-listのそれぞれの変数名は、リファレンス型になる。初期化子の要素数と同じだけの識別子がなければならない。

int a[3] = { 1, 2, 3 } ;
// ill-formed.
auto [ a1, a2 ] = a ;

変数は必ずリファレンス型になる。これについては注意が必要だ。構造化束縛にリファレンス修飾子がない場合、初期化子がコピーされて、変数名はそのコピーへのリファレンスになる。リファレンス就職しがある場合、コピーされず、初期化子へのリファレンスになる。

例えば、以下のコードは

int a[3] = { 1, 2, 3 } ;
auto [a1, a2, a3 ] = a ;

以下のコードと同じ意味になる。

int a[3] = { 1, 2, 3 } ;
auto _a[3] = { a[0], a[1], a[2] } ;

auto & a1 = _a[0] ;
auto & a2 = _a[1] ;
auto & a3 = _a[2] ;

初期化子のコピーが作られ、変数はそのコピーへのリファレンスとなる。

以下のように書いた場合は、

int a[3] = { 1, 2, 3 } ;
auto & [a1, a2, a3 ] = a ;

以下のようになる。

int a[3] = { 1, 2, 3 } ;

auto & a1 = a[0] ;
auto & a2 = a[1] ;
auto & a3 = a[2] ;

初期化子はコピーされず、変数は初期化子のオブジェクトへのリファレンスとなる。

P0218R1: C++17 Filesystem

filesystemライブラリ。

P0219R0: Relative Paths

Filesystemライブラリに相対パスを計算する機能を追加する提案。

基本的には、。あるパスに対して、別のパスからの相対パスを計算する方法で、例えば/a/b/cに対して/a/bからの相対パスを計算するとcになる。

これだけならば、現行のFilesystemにも存在するのだが、Symlinkを追ってほしい、追わないでほしい。冗長な.や..を除去してほしい。ほしくないと言った衝突するユーザーの要望があり、かつどのように振る舞うか意見が別れるコーナーケースも多数あるため、Boostでは10年にわたって紛糾している問題。これに対する解決案。

ドワンゴ広告

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

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

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

2016-06-13

rootが無効化された環境でsshfsで権限の必要なファイルを変更する方法

sshfsは便利だ。リモートのファイルシステムをローカルのファイルシステムにマウントして扱うことができる。これにより、ローカル側のGUIのファイルシステムビューワーやエディターを使った温かみののある手作業による管理ができる。

ところで、Ubuntu Serverではrootが無効化されている。そのため、sshfs root@host:remote_path local_path はできない。代わりに、root権限が必要な操作はsudoを使って行う。しかし、sshfsではsudoができない。一体どうすればいいのだろうか。

試していないが、調べたところ、sftp_serverを指定する方法で行けるようだ。

まず、sudoのcredentialをキャッシュさせるために、ssh軽油でsudo -vを実行しておく。

そして、以下のようにsshfsでsftp-serverを指定する。

sshfs user@host:remote_path local_path -o sftp_server="/usr/bin/sudo /path-to/sftp-server"

おそらく行けるはずである。

2016-06-11

プログラミング言語基礎勉強会で発表した

プログラミング言語基礎勉強会 sponsored by @wantedly UIターン - connpass

上記の勉強会で発表してきた。今回の発表は、C++17の標準ライブラリを軽く説明した。

発表に使用したスライド資料はGitHubに上げてある。

EzoeRyou/cpp17lib-slide: 勉強会のスライド資料

発表者が全員濃かったので、他人の発表はあまりよくついていけなかった。

最後に地方と都内で仕事をすることについてというテーマでパネルディスカッションがあったが、いかんせんテーマが技術的なものではないので、極めて一般なこと、例えば地方は地代が安いだの、都内は通勤ラッシュがひどいだのといった、誰でも言えるようなことしか話せず、せっかくあの人間を前に集めて議論する内容としては非常にもったいなく感じた。一体何を考えて、あの人選に対してあんな陳腐なテーマを設定したのか謎だ。

その後懇親会に参加していろいろと雑談をしていた。結局、勉強会の価値はこういう雑談にあると思うので、懇親会がメインで発表は1,2時間だけという勉強会を開いてもいい気がした。

さて、勉強会の会場の近くには、そらよんというクライミングジムがあるので、勉強会のあとに行こうと思っていたが、どうしたことか、休日は21時までしかやっていないそうだ。ジムに行った時には、すでに閉まっていた。

ドワンゴ広告

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

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

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

2016-06-09

GNU/Linuxでゲーム

数年前のゲーミングラップトップを手に入れたので、Ubuntuを入れてゲーム用のGNU/Linux環境を構築しようとした。

GNU/Linuxにおけるゲーミング環境は年々良くなってきている。ValveのSteamOSのおかげでGNU/Linuxに対応する理由があるからだ。今回の目的は、持ち運べるfactorioゲーム環境を作ることだ。

もらったゲーミングラップトップは、G-tunes Nextgear i770というものだ。Core i5 3230MにGeForce GTX670MX、メモリが12GB、ストレージが1TBのSSHDだ。メモリが12GBなのは、4GBメモリを4枚さして16GB積むと何故か起動しないので1枚抜いたとのことだ。メモリが悪いのかマザボが悪いのかはわからない。

もらった時点でWindows 10が入っていたが、容赦なくUbuntu 16.04をインストールする。Windows殺すべし。慈悲はない。

さて、インストールが終わったら。apt-get install steamしてsteamをインストールする。そしてfactorioをインストール。

いざ起動してみると、何事もなく動いた。しかしFPSが30程度しかでない。

GPUドライバーが自由なソフトウェア実装であるNouveauになっていた。涙をのんで不自由なnvidia-driverをインストールする。

nvidiaの不自由なドライバーをインストールするとまともなFPSが出るようになった。しかし、画面にティアリングが発生する。どうやっても直らない。また、xrandrを使ったディスプレイの回転ができない。また、外部ディスプレイをつなぐと、nvidia-settingsからは、一枚の巨大なディスプレイを使っているかのように扱われる。解像度が高すぎるため、一度外部ディスプレイをつなぐと、ゲームのFPSが落ちる。

調べたところ、これはnVidiaのドライバー上の問題で、今のところどうしようもないということ。nVidia Fuck You!

nVidia Optimusは、IntelのGPUとハードウェア的にもかなり密に結合していて、nVidiaのGPUがIntelのフレームバッファに直接書き込むような形になっているそうだ。

また、factorioのゲームサーバーを立てるために、適当な安い中古のラップトップを買ってきた。Ubuntu Serverをいれて、とりあえずfactorioサーバーを建てられるようにはした。中古だが、ある程度こだわって選んでしまったので、果たしてサーバーにしていいものかどうか迷う。ただし、メモリが2GBしかないため、デスクトップ用途に使うとしてもUnityはいれられないだろうから、XbuntuとかLubuntuなどを入れることになると思う。

2016-05-26

近況

しばらくブログを書いていなかったが、いろいろと忙しかった。

今、とある仕事をしているのだが、その仕事内容がまことに精神的に辛い。その仕事内容はまだ公開できないのだが、とりあえず言えることとしては、1文字は1バイトではないということと、C++の標準ライブラリの正規表現ライブラリはUnicodeに対応していないということと、C++のlocaleは多言語対応の足かせになっているということだ。

さて、もうひとつ憂うべき事態としては、メインで使っているラップトップが故障した。去年の冬頃からどうにも挙動がおかしいと思っていたが、いよいよ使い物にならないほど挙動がおかしくなってきたので、memtest86+にかけてみたところ、なんと4900件ほどのエラーを出したところで動作を停止した。完全にメモリが壊れている。

さて、メモリが壊れているだけなら新しくメモリを買ってくればいいのだろうが、このラップトップはその他のスペックが2016年の基準から見て劣っている。ディスプレイの解像度は低いし、WiFiも5GHz帯が使えない。そろそろ新しいPCを買わねばなるまい。

とりあえず今は、別件で手に入った中古のゲーミングラップトップを使っている。これは、GNU/Linuxでゲーム環境を構築するために試しに買ってみたもので、nVidiaの不自由なGPUであるGTX 670Mが積んである。とりあえずUbuntu 16.04をインストールしてみたところ、自由なドライバーであるNouveauで動作した。そのままゲームも遊ぶことができたが、FPSが絶望的に出ない。仕方がなく、nvidia-driverを入れてみると、まともなFPSが出た。しかし、なぜかXrandRが動かないため、ディスプレイの回転ができない。

ところでゲームだが、最近は、ゲームといえばfactorioしかしていない。factorioは極めて高い中毒性のある自動化ゲームで、プログラマーならば必ずハマるだろう。先週は職場の同僚5人でマルチプレイをして、10時間かかってロケットを打ち上げた。

ところで、factorioには列車があるのだが、つながった同一の線路上に複数の列車を走らせる場合、信号を使わなければならない。この信号の使い方は、ゲーム内になんの説明もない。factorioの公式wikiには、OpenTTDと同じだからそちらを参照しろとしか書いてない。

これについて列車好きの同僚に教えを請うたところ、排他処理の起源は鉄道だったという事実を知らされた。なるほど、信号で区切られた区間に存在できる列車は一つだけという排他処理なのだ。これを理解したので、ようやく列車ネットワークが組めるようになった。なんのことはない。単なる排他処理である。ただし、一つの区間のアンロックと同時に、別の区間をロックするという特性がある。

現実の鉄道の排他制御では、区間の独占通行権を示すタブレットと呼ばれる物理的なトークンをやり取りしていたようだ。また、駅間が電信でつながっていて、タブレットを入れると、数値が駅間でインクリメント、デクリメントされ、釣り合いが取れた時だけタブレットが排出される装置まで存在したそうだ。それはセマフォではないか。

自宅でのfactorioのLANパーティもいつか開きたい。

2016-05-11

BitKeeperがオープンソース化された付記DVCSの歴史

BitKeeper

BitKeeperは最初の分散ソース管理システムである。今後はオープンソースのApache 2.0ライセンスとして提供される。

BitKeeperは高速で、エンタープライズレディな、分散ソースコード管理であり、大きなプロジェクトから小さなプロジェクトまでスケールする。

「最初の」という主張には語弊があるが、DVCSの歴史を考えると、あながち間違いでもない。

DVCS(分散バージョン管理システム)を最初に実装したのは、Sun WorkShop TeamWareである。

Sun WorkShop TeamWare - Wikipedia, the free encyclopedia

これは名前通り、Sun Microsystemsによって開発されたDVCSで、その主要な開発者として、Larry McVoyがいる。

Larry McVoy - Wikipedia, the free encyclopedia

Larry McVoyはその後独立してBitMover社を立ち上げ、BitKeeperというDVCSを開発する。BitKeeperは2005年までLinuxカーネルの開発に使われていた。

BitKeeper - Wikipedia, the free encyclopedia

Larry McVoyは、1990年台前半に、Sun MicrosystemsはSunOSをオープンソース化すべきであると主張していた。

The Sourceware Operating System Proposal

もし実現していれば、Linuxは今日の興隆を見なかったかもしれず、我々はSunOSを使っていたかもしれない。

そもそも、Sunの生い立ちたるや、IBMのメインフレームのような巨大で高価なコンピューターに対して、より小型で安価なUnixワークステーションを販売して成功したというものだ。とすれば、次は個人でも所有できる、さらに小型で、さらに安価なPCが流行するというのは、自身の成功体験から予測できたはずである。PC用のハードウェアを売る商売でSunは儲けられたはずであり、OSは自由にできたはずだ。我々はIBM PC互換機ではなく、Sun PC互換機を使っていて、WindowsやGNU/LinuxのかわりにSunOSを実行していたかもしれない(Sunのユーザースペースツールは使いづらいのでGNUはまだ残っていたかもしれない)。

にもかかわらず、Sunは近視眼的な判断によってSunOSをオープンソースにはしなかった。

さて、1993年にSunOSのオープンソース化を主張したLarry McVoyは、残念ながらその主張を実践しなかった。BitMover社を立ち上げてBitKeeperを開発したが、BitKeeperはプロプライエタリであった。2005年まで、Linuxカーネルの開発に使われていたが、無償版で提供されていない機能を実装したLinuxカーネル開発者であるAndrew Tridgellの行為に激怒してコミュニティへのBitKeeperの提供を辞めた。

そして、gitが生まれることになった。gitは圧倒的な速度でDVCS市場を独占していき、BitKeeperなど誰も相手にしなくなった。そして今日に至る。

残念ながら、BitKeeperのオープンソース化は、10年遅かった。もう手遅れだ。

2016-05-08

xkcd 463: 投票機

xkcd: Voting Machines

Premier Election Solutions社(以前はDiebold社)は、自社で開発したオハイオ州の選挙用の投票機が、McAfee アンチウイルスソフトウェアの問題によって障害を起こし責任を追求されている

「ちょっとまて」
「投票機にアンチウイルスソフトウェアだと? 間違ってるだろ」

「なんで? セキュリティは重量だろ?」
「もちろんそうだが、なんと言うべきか」

「保護者の教師の説明会で、教師が授業中は常にコンドームをつけているので安全だと保護者の説明したとしよう」

「なるほど、厳密に考えると、付けていないよりは安全・・・」
「間違ったやり方のヤツがいかに多いことか」

titleテキスト:これで俺はまた暗号会議を追い出された。いいだろ。いい例えなんだからさ。

2016-05-05

MITがSICPを教えなくなった理由

Programming by poking: why MIT stopped teaching SICP | posterior science

このNYC Lisp meetupの動画で、Gerry Sussmanに対する質問として、SussmanとAbelsonの古典、The Structure and Interpretation of Computer Programs(SICP)に基づく、伝説的な6.001講義をなぜMITはやめたのかと聞かれている。

Sussmanの回答としては、SussmanとHal Abelsonは1980年代から延々と教え続けるに嫌気が差し、1997年に、学部長の事務所に行って、「俺らはやめる。後どうするからは勝手に考えろ」と宣言した。より重要なこととしては、SICPのカリキュラムは、今日のエンジニアリングに求められるエンジニアを育てることができないからである。1980年代と1990年代には、エンジニアは複雑なシステムを組むのに、単純で十分に理解されている部品を組み合わせた。SICPの目的は、そのようなシステムを理解するための抽象的な言語を提供することだ。

今日では、状況が変わっている。今のエンジニアは、自分が完全に理解していない複雑なハードウェアのためのコードを日常的に書いている(そして、大抵の場合、企業秘密により完全に理解するのは不可能である)。ソフトウェアでも状況は同じだ。プログラミング環境は、多大な機能を提供する巨大なライブラリ群の集合として存在している。Sussmanの今日の生徒は、その時間の大半を、ライブラリのマニュアルを読み、どのように組み合わせれば目的が達成できるのかを把握することに費やしている。Sussman曰く、今日のプログラミングは、「より科学に近い。ライブラリを持ち寄って、つっつき回すのだ。プログラムを書くには、突っつき回して、どのように動作するかを観察する。そして、「目的を達成するために改造できるか」と考えるのだ」。SICPの「合成による解析」という物の見方である、小さな、単純な部品を組み合わせて大きなシステムを作るということは、もはや今日の状況にそぐわなくなった。今や、我々のプログラミングはつっつき回すことで行われている。

なぜPythonを選んだかということについて、Sussmanは、"late binding"に決定したと冗談を飛ばした。Pythonには大量のライブラリがあり、教育者の様々な実習に使いやすい(たとえば、ロボットを制御するソフトウェアを書くなど)

Sussmanは、SICPカリキュラムは現在のカリキュラムより洗練されていると考えているものの、正しいカリキュラムのあり方についてはまだ答えが出ていないという。

たしかに、今のプログラマーは、ハードウェアの仕様書を元にを直接操作するコードは書かないし、OSを実装していないし、コンパイラーも実装していないし、古典的なアルゴリズムやデータ構造さえ自分の手で書く必要がなくなっている。ライブラリが発達してその必要がなくなったためでもあり、また個々の機能があまりにも高度になりすぎて、到底一個の人間の手に負える作業量ではなくなったということもある。

不自由なハードウェア、ソフトウェアが蔓延してその詳細がわからなくなり、また自由なソフトウェアであっても、その内容が複雑になりすぎ、一つ一つ完全に理解するには時間が足りなすぎる。

何にせよ、平均的なプログラマーが実現できる機能は昔よりはるかに複雑になっていることは確かだ。

2016-05-02

Craig WrightがSatoshi Nakamotoだとする証明はない

WiredとGizmodeにより、Craig Wrightなる人物がbitcoinのオリジナルの設計者にして最初の実装者、Satoshi Nakamotoであると報じている。

Bitcoin’s Creator Satoshi Nakamoto Is Probably This Unknown Australian Genius | WIRED

This Australian Says He and His Dead Friend Invented Bitcoin

bitcoinのオリジナルの設計者にして最初の実装者は、当時Satoshi Nakamotoと名乗っていた。一見、日本人のような名前であるが、彼は自らのことを多く語らず、またできるだけ身元の特定に繋がる痕跡は隠していた。当然、国籍はおろか、個人かどうかすらもわからない。彼の書いたコードのコメントはすべて英語で、非英語ネイティブにありがちな文法ミスはみあたらない。また、彼の当時のフォーラムへの500件ほどの投稿を調べると、GMTで5時から11時にかけてほとんど投稿がみられないので、Satoshi Nakamotoはこの間には睡眠をとっていたのではないかと推測されている。この時間帯はJSTに生きる人間の一般的な睡眠の時間帯とは異なっている。

Satoshi Nakamotoの正体には様々な憶測が飛び交い、日本人である京大の望月新一教授や、たまたまSatoshi Nakamotoという名前であるアメリカ人がメディアによって正体であると噂されたりもした。

さて、このCraig Wrightなる人物は、自ら作者であると名乗りでた人物であるが、発言がまるででたらめであると言われている。Bathurst大学で博士号を取ったと自称しているが、大学は否定した。また、彼のブログによる証明というのも、bitcoinの公になっているハッシュ値にすぎず、ブログで提示しているbase64っぽい文字列に至っては、デコードすると単なる平文のブログ本文にもある文字列になるというお粗末さである。

Jean-Paul Sartre, Signing and Significance - Dr. Craig Wright BlogDr. Craig Wright Blog

そもそも最も簡単な照明である、当時Satoshi Nakamotoが使っていた最初のPGP秘密鍵で署名した、「Craig WrightはSatoshi Nakamotoである」というメッセージを出して、少なくともSatoshi Nakamotoが当時使っていたPGP秘密鍵は所有しているという証明をしていない。

よくある詐欺師であり、目的はSatoshi Nakamotoを自称して出資を引き出すためではないかと言われている。

と、ここまでならよくある話だが、何故か今回の話にはおまけがある。bitcoin開発者であり、当時のSatoshi Nakamotoとも対話していて、暗号理論も理解していて証明の真贋も見分けることができるであろうGavinが、Craig Wrightは確かにSatoshi Nakamotoであるとコメントしているのだ。

このため、bitcoin開発者はGavinのコンピューターがハックされた可能性を考慮して、Gavinからコミット権限を取り消す措置をしている。まだGavinからハックされたというコメントはない。

Peter Todd on Twitter: "FYI, @gavinandresen's commit access just got removed - Core team members are concerned that he may have been hacked. https://t.co/7re7z16TeR"

ちなみに、Gavinがハックされたとか詐欺に加担しているのであれば、最も簡単に利益を上げる方法が取られていない。すなわち、「私はサトシだ。今から私の持っているbitcoinを全部売る」と宣言して、bitcoin取引市場に多大な売り注文がやってくると誤認させ、市場を混乱に陥れてbitcoinの価値を下げたところでbitcoinを買い占め、市場が落ち着いた後で売り払うという方法だ。

Satoshi Nakamotoが今更名乗りでても、それ自体は別に興味深くはない。本人の名声とか政治的迫害を別にすれば、Satoshi Nakamotoでなければできない設計や実装は今さら存在しない。ただし、Satoshi Nakamotoのウォレットに入っているbitcoinは莫大であり、市場に放出された場合、大混乱に陥るだろう。

こういった事情により、一概に詐欺とも言いがたい事態となっている。

コンピューター科学のアカデミック業界の残念な現状

mhoye on Twitter: "Extremely angry with the state of academic CS research right now. (1/n)"

MozillaでFirefoxのエンジニアリングコミュニティマネージャーであるMike Hoyeが、コンピューター科学におけるアカデミック研究の残念な現状に激怒している。

コンピューター科学のアカデミック研究の現状に激怒している。

MozillaがBugzillaを始めとした多数の情報を公開した結果として、多くの研究論文が書かれている。

我々はそのような研究には注目している。論文はじっくり読んでいるし、研究結果にしたがって今後の方向性も決めている。

しかし、我々は常に変化する世界に生きている。そのため、我々はデータをもとに結果を再検証して、仮定が正しいことを確認する。

ここで我々が行いたいことは、我々はある意思決定をある論文Xの結果をもとに行いたいのだが、その結果は最新のデータでも妥当であろうか? と言えることだ。

まともな世界では、そのような検証は以下の3ステップで行えるはずだ。

  • 論文著者のバージョン管理システムのレポジトリをクローン
  • 論文著者のプログラムを最新のデータに対して適用
  • 新しく生成されたグラフを見る

データはまだ仮説を支持するものであるか? 素晴らしい。この方向で進めよう。結果が変わった? 何故なのか考えてみよう。いずれにせよ。全員が満足する結果となる。

しかし、これは実現しない。なぜならば、コンピューター科学の研究者はコードもデータも公開しないからだ。奴らはLatexで整形したWordドキュメントをペイウォールに阻まれたPDFとして公開する。

奴らときたら、科学の原則である、「妥当性」とか「再現性」とか、中でも最も基本的な原則、「現実に即しているか」などは、クソ喰らえの姿勢だ。

人間が知識や学習結果を共有しないことの時代遅れがいかに時代遅れであるかを見てみようか。

ギリシア火薬の製法は失われた。ダマスカス鋼の製法は失われた。アンティキティラ島の機械は紀元前200年に失われ、同等の精度を持つ時計を再び作るには1500年代まで待たねばならなかった。

いいか。よく聞け。お前の未公開のコードと、お前の未検証のデータと、お前のペイウォールに阻まれた博士論文は、この輝かしい因習の一部であるのだぞ。

お前の目的とやらが、学士を得て卒業することなら、まあいいだろうよ。大抵の人間が望むことだ。だが、院にまで来てやることか?

お前の業績により世界をよりよい方向にインクリメントするためには、世界はお前の業績を読めなければならないのだぞ。

俺は結果の報告書など読みたくない。そんなのは、ワインを注文しているのに、赤っぽい色の液体について報じた新聞記事の切り抜きをFAXしてよこされるのと同じだ。

検証可能なデータと動くコードなしには、お前のコンピューター科学の博士論文の命題とやらは命題ではない。それは単に命題が存在するかもしれないという未検証の主張に過ぎない。

まとめると、俺は大変に失望している。もっと言うべきことはあるが、俺はこれから長年の研究とツールを再現するためのコードを書かねばならないのだ。

2016-05-01

超会議2016でドワンゴの運営スタッフとして焼きそばを焼いた感想

「江添さん、超会議で焼きそばを焼きませんか?」

恰幅のいい同僚が話しかけてきた。この男はドワンゴの料理研究部の部長である。

ドワンゴには福利厚生として同好会の設立を会社に申請でき、受理された同好会には部費も支給される。最も、会社が経費として出す金なので、いろいろと制約がある。例えば、飲食費用には使えない。料理研究部は調理器具や職場近くのキッチンのレンタルなどに部費を使っている。

「焼きそば? 少し前に話題になったアレをネタにするつもりですかな。しかし、もう旬は過ぎてしまったのではありませんかな」

「アレ」というのは他でもない。一時期、ドワンゴから退職が相次いだ時期があり、その時のある退職者に対して、退職理由がよくわからないとドワンゴの川上宣夫会長と伊藤直也氏がスシをつまみながらのインタビュー記事で書かれたことを受けて、元ドワンゴ社員のkuzuhaが、言及されている退職者というのは自分であろうと名乗りでて書いたブログ記事が発端で、一時期ドワンゴと焼きそばが炎上したアレだ。

僕は初回のニコニコ超会議が開催される前にこの話を聞いてさっさと退職したので実際には経験をしていませんが、ニコニコ超会議には社員が強制的に動員され、列の整理や焼きそば屋台などに従事させられました。正直に言ってソフトウェアエンジニアとして雇用した人間に焼きそばを焼かせるのは雇用契約違反なのではないかと思います。立て付けとしてはお客様の文化に触れる、本気で楽しんでくださっているお客様の姿をじかに見られる他にない機会であるという言い分です。

ドワンゴは大量退職に関する印象操作をやめろ - hiroki-uemuraのブログ

この炎上以降、Googleの検索欄に"ドワンゴ"と入力すると"焼きそば"がサジェストされ、"ドワンゴ 焼きそば"でググると、ドワンゴに対してネガティブな情報ばかりヒットするようになってしまった。

私がドワンゴに入社する以前の話であり、この当時の状況は人からの伝聞と風のうわさでしかわからないのだが、kuzuhaの記事には間違いがある。初代超会議のフードコートでドワンゴのエンジニアに課された料理は「焼きそば」ではなく「あんかけチャーハン」だったとのことだ。当時、ドワンゴの社内チャットでは、「会社は焼きそばではなくチャーハンですと訂正するIRを出すべきでは」などと無責任な冗談が飛んでいた。

ところでチャーハンといえば、ドワンゴには非公認のチャーハン部があり、名にし負うハンドルネームがチャーハンである部長の強力なリーダーシップのもと、毎週一度近所の中華料理屋に臨んで大盛りのチャーハンを食らうという活動をしているが、同部ではチャーハンの重量以外に、食べづらさ、胃もたれなどの完食への困難性への度合いを総合的に評価した、実質係数なる独自用語が飛び交っていて、1.2kgのチャーハンを完食した部員は尊敬され、中でも、1.2kg完食者の「来る者拒まず、去る者追う」という発言は名言としてSlack上で永久にPinされている。

それはさておき、同僚の話によれば、転んでも無料では起きない精神をもってこの炎上ネタを利用し、来る超会議2016ではエンジニアがフードコートで焼きそばを焼く企画があるという。そのために、フードコートに自らの意思でアサインされるエンジニアを募集しているという。

「いえね、やはりこういう企画は表に名前の出ている有名なエンジニアさんを採用したほうがいいと思いますし、焼きそばを焼くのも悪くありませんよ。なんでしたらフルタイムではなくパートタイムでも構いません。基本的には他のブースにアサインして途中2時間ほど抜けて焼きそばを焼くという形でのエンジニアの参加も予定しています。焼きそばを焼いていただけるのでしたら、特別に企画にかけあって希望のブースに優先的にアサインされるような配慮も致します。そしてですね。あまり言いふらしてほしくないのですが、休憩時間を通常1時間のところ、焼きそばブースは特別に2時間取ろうと予定しております」

「ほう、2時間?」

「はい、といいますのも。焼きそばを焼く鉄板はすごく熱くなるので、普段から仕事で焼きそばを焼く本職の人でも3,4時間ぐらいが限界だとか。我々素人に換算しますと、もっと短い時間で限界になるでしょうし、休憩時間も多めに必要なわけです」

巨体に似合わぬ高い声で、同僚は官僚的な勧誘文句を連発する。実際、この同僚はこの手の官僚的な細かい規則主義、手続き主義を極めて得意とする男であり、その才能は公私において遺憾なく発揮されている。今回のこの企画に割り当てられたのもその才能故だろう。この企画を遂行するにあたっては、外部のイベント設営会社、イベント運営会社、ましてや食品を扱うので消防、保健所などとの極めて役所的で煩雑なやり取りをしなければならないだろう。

そういえば、この同僚はドワンゴ社員の労働組合の代表でもあった。以前、ドワンゴとドワンゴ社員の労働組合との労使協定が危うく締結できなくなる危機があった。理由は会社と労働者との待遇の提示と要求の不一致という高尚なものではなく、単にドワンゴ社員がズボラで会社と労使協定を締結する際の労働組合の代表を選ぶ投票に参加しないというだけであった。

雇用者と被雇用者の労働組合との間で労使協定が締結できない場合、何が起こるのかというと、労働基準法の定める範囲外の労働が違法になる。読者の中には、労働基準法の範囲内の労働しか認められないのはとても良いことではないかと考える人もいるだろう。もしそう考えているとしたら、読者は労働基準法を読んだことがないだろうから、今すぐ読むべきである。

労使協定を結ばない労働基準法の定める範囲内の労働というのは、極めて制限が強い。一日の労働時間は最大8時間であり、1週に最大40時間である。残業や休日労働は認められない。緊急時のみ認められるが、事後に行政に残業や休日労働を行った旨を届け出なければならない。これは、夜中や休日にドワンゴの提供するサービスに障害が発生した場合でも、次の営業日の営業時間になるまで修正作業が行えないことを意味する。例えばニコニコ動画でそのような障害対応を行った場合、ユーザーが可及的速やかに離れてしまうだろう。Webサービスにおいては、障害はいつ何時でも即座に対応しなければ死活問題なのだ。また、定時が存在するようになり、全労働者は同じ時間に一斉に出社し、同じ時間帯に一斉に休憩を取り、同じ時間に一斉に退社することになる。

もちろん裁量労働制はなくなる。ドワンゴの特に極端な社員の一日では、早朝に就寝し、昼過ぎに起床して出社し、出社で疲れたので仕事など当然できるわけもなく、まず飯を食いに行き、16時から朝会と称する部署のメンバーが集まっての活動報告を行い、18時頃からそろそろ昼になってきたから本腰を入れて仕事するかなどとうそぶきながらようやく活動を始める。そんな裁量労働制もなくなってしまう。

事態は極めて逼迫しているというのにドワンゴの労働者はどこ吹く風といった時、この同僚は各個撃破の地道な根回しを行って何とか票を集めて従業員代表になり、労使協定を締結させ、ドワンゴの裁量労働制を維持し、ひいてはドワンゴの労働基準法違反を回避させた男である。

かかる経緯で、筆者は超会議2016で焼きそばを焼くことになった。

なお、フタを開けてみると、この同僚の根回しが強力すぎたためか、はた、祭り好きの人間が多かったのか、焼きそばブースへのアサインを希望するドワンゴのエンジニアが応募多数に付きお断りする事態が発生していたらしい。

そもそも元をたどればこの焼きそば企画の発端は、kuzuhaの上記のブログ記事なのだが、この企画を社内で提案した人間は、実は途中で退職しているそうだ。そのため、同僚は退職者の企画を引き継いだ形になる。この規格の経緯を考えるとなんとも形容しがたい何らかの違和感のある不思議な気分になる。

今回の焼きそば企画では、"ドワンゴ 焼きそば"でググった時の検索結果のネガティブな結果を変えようという意図もあるらしい。なんと、物理SEOというわけか。当日はよりシュールなネタとして、特別なスタッフカードを装着することとなった。そのスタッフカードには、顔写真と名前と「私は自らの希望で焼きそば担当になりました。」とそらぞらしく書いてある。

この同僚の苦労はともかく、焼きそばブースにアサインされただけのエンジニアは、前日のリハーサルと当日の本番に労働するだけであった。

リハーサルの日は雨が降っていた。焼きそばブースの現地でのリハーサル開始として指定された時刻は16時であった。これは朝が弱いエンジニアへの配慮である。というのは方便で、実際には、消防と保健所の検査が終わるまで鉄板に火を入れることができず、調理実習ができないためである。筆者は大幅に寝坊をして現地の到着が15時半になったが、ブースには誰もいなかった。しかたがないのでニコニコ頂神社の壁を登っていた。グレードは8級以下に感じた。今回のビレイは派遣されたプロが担当するそうだ。焼きそばもプロが派遣されているという。今回、ボードゲームがないのは残念だ。

16時になったのでフードコートに戻ってみるが、やはり誰もいない。まさかと思って控室に行くと、全員いた。エンジニア達は爪楊枝にN高のシールをはって食べ物に指す旗を作るという地味な単調作業をしていた。エンジニアの人件費を考えると、この旗は相当高いに違いない。しかし不思議だ。プログラマーにとって単調作業は忌避すべきものであるが、我々はたまに単調作業の魅力に惹かれてしまう。これは一体どういうわけだろう。

その後、待てども待てども検査はなかなか始まらず、とうとう前日は調理実習が何もできないまま解散した。筆者はその足で、海浜幕張にあるPEKIPEKIというクライミングジムに行った。去年登れなかった課題がまだ残っており、しかも登ることができた。また、クライミングマシーンのExtream設定をクリアした。一年たって上達を感じる。

さて、当日、ようやく鉄板に火を入れることができるようになったので、焼きそばのプロの実演を見た。出来上がったカレー焼きそばを食べたが・・・とても粉っぽくて食べられたものではない。どうやらレシピに記載されたカレー粉の分量が多すぎるようだ。調整してまともな味にした。

今回の焼きそばには、ドワンゴのニコニコ動画チームのK1の設計したカレー焼きそば、ニコニコ静画チームのまさらっきが設計したイカスミ焼きそば、ニコニコ生放送チームのK2が設計したピザ焼きそばの3種類の焼きそばが用意されている。カレー焼きそばには、カレー粉が入っている。イカスミ焼きそばにはイカスミが入っている。ピザ焼きそばは肉の代わりにシーフードミックスで、トマトピューレを入れた上で、上からパルメザンチーズをかける。

今回、焼きそばブースにアサインされたレシピの設計者はまさらっきだけだ。試食の結果、イカスミ焼きそばが一番美味しかった。まさらっきはグルメをわかっているものと見える。問題は、唇と歯が黒くなってしまうバグが発覚したことだ。

ピザ焼きそばは、極めて粘着質で、パック詰めが難しいという運用上の問題が発覚した。

今回は、オープンソース焼きそばということで、レシピがGitHubで公開されている。ライセンスは煮るなり焼くなり好きにしろライセンスだそうだ。

dwango/yakisoba-sauce: Open source recipe of yakisoba-sauces for chokaigi 2016

とはいえ、物理的存在に自由不自由の区別は存在しないのだが。

売上としては、カレー焼きそばが最も多く売れ、イカスミ焼きそばが最も売れないという結果になった。

価格は800円だそうだ。焼きそばにしてはやたらと高い。イベント価格とは言えあまりの高い値段に罪悪感がある。とはいえ、後述する焼きそばを焼く労働の辛さを考えると、妥当ではないかと思えるようになってしまった。

さて、肝心の焼きそばを焼く労働の苛酷さについて述べる前に、もうひとつ書いておくことがある。エンジニアとしての演出だ。

せっかくだから鉄板の温度を計測して表示してはどうか、また、焼きそばのそれぞれの売上もカウントして表示してはどうかと、アサインされたエンジニアの一人が主張し、実際にそのための装置を作った。その実装が笑えるほど面白かったので紹介する。

まず、鉄板の温度の計測方法であるが、接触するセンサーは衛生上問題があるので使えない。赤外線のセンサーを用いることにした。そのため、中国製の赤外線センサーを買った。さて、赤外線センサーを分解して、中身だけ取り出し、温度情報を取得すればいい。ドワンゴの電子工作部の部員に依頼したが、温度情報を取り出す方法がわからない。唯一測定できる信号線は、液晶ディスプレイにつながっているもので、0.1mm以下の線が何本もあり、これを手作業でハンダ付けして一本一本取り出すのは極めて困難なのでやりたくないとのことであった。したがって、計測装置は極めて笑える富豪的な実装になった。

すなわち、温度を表示する液晶ディスプレイをカメラで撮影し、画像認識して温度を得るというものである。このためにカメラとRaspberry Piが用いられた。

しかし、残念ながら、当日の表示に温度表示がつくことはなかった。理由はわからないが、鉄板の温度が60度ぐらいに表示されてしまうのだ。表面に塗った油が煙を出すような状態でその温度は明らかにおかしい。この赤外線温度計は確か500度まで対応していたはずだがなぜだろうか。あるエンジニアは、鉄板の温度が高すぎてオーバーフローしたのではないかという説を出した。温度が9bitで管理されていた場合、512度以上になるとオーバーフローする。しかし、9bitなどという中途半端なビット数で管理するだろうか。「いや、ビット数を増やすと信号線が増えて回路も増えて手間もコストもかかる。組み込みならよくあること」と言っていた。

しかし、冷静に考えると鉄が600度になると赤黒く発光するはずであり、そんなに高温になるだろうか。

「もう乱数でも表示しておけばいいんじゃないか。どうせ気づかないぜ」などという冗談まで飛び出した。

さて、焼きそばの種類ごとの売上をカウントするボタンはうまく機能した。ボタンは、100円ショップで売っていそうな透明なタッパーを容器として、ボタンを3つ取り付けてある。容器の中には基板が入っていた。

「それはArduinoかな」
「ラズパイですよ」
「ラズパイ? たかがボタン3つの制御のために?」
「何言ってるんですか。富豪的プログラミングって言葉知ってます?」
「たかがボタン3つの制御のために一昔前のスマフォに組み込まれていたARM CPUと100MB以上のメモリが必要なのか?」
「今はIoTの時代ですよ。ボタンもsshdぐらいお話できないと不便ですよ」
「ボタンの制御にH.264をデコードできるGPUを詰んだMinecraftもインストールされているコンピューターが必要なのか?」
「それは・・・うーむ」

3つボタンの容器は2つあったので、このシステムにはRaspberry Piが3つも使用されていることになる。なお、実際にはログの集計に使うソフトウェアにメモリが16GB以上必要でMacBookまで持ち出すはめになった。富豪的プログラミングにもほどがある。

さて、そろそろ肝心の焼きそばを焼く労働について述べねばなるまい。当日のフードコート奥には、3枚の鉄板が設置された。一枚の鉄板で一度に40人前(パック詰めのときには、目分量でかなり多めに詰めたので、実際にはもっと少ないだろうが)の焼きそばを焼くことができる。カレー焼きそばの材料は、豚こま切れ肉1.5kg、キャベツ1.5kg、カレー粉適量、もやし2kg、麺4kgである。

このスケールでは、焼きそばの調理は重労働である。まず鉄板が熱い。読者は何をいまさらと思われるかもしれないが、やはり鉄板は熱い。焼きそばをかき混ぜるには、ヘラを動かすために鉄板の上に手をかざさなければならず、極めてあつい。そして材料は重い。まさか焼きそばの麺があれほど重たいものだとは思わなかった。

そして、焼きそばは休みなしにひっきりなしに焼かねばならなかった。というのも、作ったそばから売れて在庫がなくなっていくからだ。会場には焼きそばの保温器が設営されていたが、果たして必要だったのだろうか。

フードコートのボトルネックは注文を聞いて現金をやり取りする部分で、そのためにスループットが上がらず行列ができてしまうのだが、たとえそのボトルネックが解消されたところで、焼きそばの生産速度はすでに追いつくのも難しいほど限界であった。

また、パック詰めも焼きそばの調理ほど肉体疲労はないが、地味に手間のかかる面倒な作業であった。トングで焼きそばを掴んで、パックにいれ、輪ゴムをかけなければならないのだ。カレー焼きそばとイカスミ焼きそばは普通の焼きそばなのだが、ピザ焼きそばはトマトピューレを入れるため、やたらと粘着質な出来上がりになってしまい、トングで掴んでパックに移す作業が極めて面倒であった。

興味深いのは、フードコートの売れ行きである。行列ができていると呼び込まずともどんどん人が来るのだが、行列ができていないとまるで人が来ない。これは一体どういう群集心理が働いているのだろうか。先の単調作業への魅力といい、なんだかやたらと心理学への興味が深まる。

こうして、過酷な2日間に渡る焼きそばブースでの業務が終わった。始まる前は、「ところで、ちゃんと焼きそばは食べられるんでしょうね? 目の前で焼いているのに食べられないとか拷問ですよ」などと言っていたエンジニアは、あまり焼きそばを食べていた気配がない。

超会議のフードコートで焼きそばを売って実感したこととしては、希望せずに強制的にフードコートに配属されたら、少なくとも転職を考えるぐらい疲労するということだ。

だいぶ披露したとはいえ、ボルダリングは別腹だ。超会議2日目の後は海浜幕張のクライミングジム、PEKIPKEIには行った。前日リハーサルで落とせなかった課題が落とせたので満足して帰った。来年もまたこよう。

写真

ドワンゴ広告

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

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

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

2016-04-23

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

Ubuntu 16.04にアップグレードした。今回はかなり問題だらけだった。

まず、アップグレードが正常に終わらなかった。古いパッケージを削除する途中で、hicolor-icon-themeのインストールスクリプトが正常に終了しなかったとのメッセージが表示された。同じ問題が報告されているようだ。

Bug #1571139 “package hicolor-icon-theme 0.15-0ubuntu1 failed to...” : Bugs : hicolor-icon-theme package : Ubuntu

他にも、Localesのインストールスクリプトが正常に終了しなかったというメッセージも表示された。

そして、"E: mkinitramfs failure cpio 141 gzip 1"と表示されたまま画面が完全に固まってしまった。入力を一切受け付けず、端末に切り替えることもできなければ、SysRqもきかない。30分ほど待っても何も起こらないので、仕方なく電源を落とすことにした。

さて、ブートしてみるとGrub2のシェルが表示される。さて、ブートローダーの問題なのだろうか。

とりあえずUbuntu 16.04のISOを落としてブータブルUSBメモリを作成してブートしてみる。あっさりとブートできた。どうやらLive USBではなくて普通にUSBメモリのブートローダーだけを使ってラップトップにインストールしたUbuntuが起動したらしい。ログイン画面は16.04になっている。

それではgrubのインストールだけやり直せばいいのだろうか。とりあえず様子を見てみようとGUIのアップデートプログラムを起動してみたところ、何やら大量のパッケージを確認もなくアップデートして再起動を促された。はて、まだ終わっていなかったのだろうか。

再起動してみるとこれまた普通に使える。古いパッケージ、特に古いLinuxカーネルのパッケージが大量に残っているので、apt-get autoremoveで除去した。

さて、今回はGCCが5.3、Clangが3.8になっている。ただし、libc++とlibc++abiに問題があるようだ。まず、libc++abi-devは、/usr/include/libcxxabi/下にインストールされるのだが、このディレクトリへのパスが通っていない。しかし、なぜか/usr/include/c++/v1/cxxabi.hだけは存在するので/usr/include/libcxxabi/__cxxabi_config.hを#includeしようとして見つからないエラーが出る。

仕方がないので、Clangのオプションに-I/usr/include/libcxxabi/を渡してパスを追加した。

もうひとつ、どうもlibc++ 3.7のstd::stringの実装に問題があるようだ。/usr/include/c++/v1/stringの1326-1331行は以下のようになっているが、

    _LIBCPP_INLINE_VISIBILITY explicit basic_string(const allocator_type& __a)
#if _LIBCPP_STD_VER <= 14
        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value);
#else
        _NOEXCEPT;
#endif

1936-1940行は以下のようになっており


template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
    : __r_(__a)
{

basic_stringのコンストラクターの宣言にあったnoexceptが定義には存在せず、宣言の不一致でエラーになる。

パッケージ管理されているファイルを弄りたくはないので、とりあえず別のディレクトリにコピーしてコードを修正し、そのディレクトリへのパスを追加することで修正した。次のUbuntuのアップグレードの時まで忘れずに覚えていなければならない。

変更自体は、noexceptを付けるだけだ。


~/Documents/src/cpp/include$ diff -u /usr/include/c++/v1/string ./string 
--- /usr/include/c++/v1/string 2015-09-06 19:01:16.000000000 +0900
+++ ./string 2016-04-23 18:59:51.848010811 +0900
@@ -1936,6 +1936,11 @@
 template <class _CharT, class _Traits, class _Allocator>
 inline _LIBCPP_INLINE_VISIBILITY
 basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a)
+#if _LIBCPP_STD_VER <= 14
+        _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+#else
+        _NOEXCEPT
+#endif
     : __r_(__a)
 {
 #if _LIBCPP_DEBUG_LEVEL >= 2

2016-04-20

江添ボドゲ会@5月

以下の通り5月7日に自宅でボドゲ会を開催するのでお集まりください。

江添ボドゲ会@5月 - connpass

今回もカレーでも作ろうと思う。

curl | bashをサーバーサイドで判定する方法

Detecting the use of "curl | bash" server side | Application Security

ソフトウェアをインストールするとき、シェルスクリプトを実行するのはよくあることだ。しかし、そのシェルスクリプトが他人のリモートサーバーでホストされていた場合、curl | bashするのは危険だ。まともなユーザーは、curl | bashする前に、まず中身を確認して、悪意がないことを確かめるものだ。

しかしもし、サーバー側がwgetやcurlといったツールとブラウザーを判定して、それぞれ別のコードを返した場合どうか。ユーザーが見るのは囮のシェルスクリプトだ。

しかし、それではcurlやwgetを利用してシェルスクリプトをダウンロードするユーザーは騙せない。しかしもし、curlとcurl | bashを判定することができたらどうか。実は、できるのだ。

curlとcurl | bashを判定する方法は、bashの処理にある。bashはコードを順次実行していく。コードの実行中はパイプからの読み出しが滞る。ネットワークとパイプのバッファーが全て埋まってしまえば、サーバーからのデータのダウンロードは中断する。したがって、コードの冒頭にsleepを置いて、バッファーを埋めるために無害で表示されないnull文字を送りつける。ダウンロードが途中で中断すれば、curlはパイプを経由してbashに出力しているのだと判断できる。

curl | bashを判定するサーバーを判定する方法

では、ユーザーはどうやってcurl | bashを判定するサーバーを判定すればいいのだろうか。判定が上に述べたような簡単なディレイで行われているならば、そういうディレイを発生させてやればよい。

curl https://example.com/setup.bash | (sleep 3; cat)

しかし、curl | bashを判定する方法はその他にもあるし、ディレイを複数使って判定することもできるので、確実に判定はできない。信頼できないデータはまずローカルのファイルに落として、中身を検証してから、ローカルのファイルをbashで実行すべきだ。

2016-04-12

Brian Kernighanがプログラミング言語Goの組版に使ったのはなんとtroff

Ramakrishnan Muthukrishnan - Brian Kernighan on the typesetting of "The Go Programming Language" book

L&RのKでありAWKのKでもあるBrian KernighanとAlan Donovanの執筆したThe Go Programming Language(邦訳は丸善からプログラミング言語Goとして6月15日に出版される予定)の組版には、Troff(具体的にはgroff)が使われたそうだ。同本の組版に感心した人間が、Brian Kernighanに組版について以下のようなメールを送った。

親愛なるKernighan教授へ

プログラミング言語Goの本のとても組版が美しい。個人的な感想では、LaTexでクマれたものより美しいように思われる。

同本の執筆手順と本の組版について詳しい説明を願いたい。著作権の項目に使ったツールについては書かれているが。

謝意

Ramakrishnanより

その結果、Kernighanから以下のような返事が返ってきたという。

Ramakrishnanへ

組版について褒めていただきありがたい。組版の大半は単にtroff(実際にはgroff)と-msマクロパッケージで行われた。Latexも少し試したが、私もAlanもその出力をさらに編集する気になれなかったし、Latexを使って組版するのは不可能だと思っている。Troffは私のよく知る昔ながらのツールで、汚く例外的な挙動も多いが、文字を組みたい場所に置いてくれることは確かだ。

入力はXMLで、見出し、パラグラフ、索引、プログラムコード辺、簡単な表などを25個ぐらいのタグで表現している。Goのプログラムでこれを変換した。素早く画面上で見るためと、もし機会があればe-book版のためにHTMLにするのと、印刷のためにtroffにする。XMLを使うのは執筆時にすこし面倒だったが、エラーチェックが便利だった。

細かい修正のために多数のgoプログラムとスクリプトを書いた。例えばすべてのページが同じ高さになるようにtroffの出力を書き換えるとか。生成されたpostscriptにも印刷所の印をいれるために手を入れている。

フォントはAlanの選択だ。適切なフォントを見つけて適切なサイズと見た目にするのにかなり労力を使った。いくつかのアジア圏の文字はうまく扱うのが難しかった。troffは全角Unicode文字を適切に扱えないので、テキストを書きかえてごまかした部分がいくつかある。

図はぜんぶAlanの仕事だった。Googleのドローイングプログラムを使った。pic[画像?、ソフトウェアの名称?]を少し試してみたが、便利ではなかったし、HTMLで扱うためには面倒だった。上付き文字以上の組版が必要な数式は使わなかったし、表は簡素なものだった。eqnとtblぐらいあれば足りるが、HTMLでは扱っていない。

もう少しドキュメントを整備してツールも公開すべきなのだろうが、ほとんどの読者は君のように過程に興味はない。もうひとつの問題として、始めた当初は綺麗で筋の通った設計だったのに、結果として過程は炎上したし、やたら複雑なmakefileを書く必要に迫られた。

メールをありがとう

Brian

ちなみに、GNUのtroff互換実装であるgroffは、ここ10年ほどメンテナーがいなくて保守されていない。

ドワンゴ広告

アスキードワンゴ編集部はlatexを使っているそうだ。ちなみに、日本の殆どの出版社はInDesignで組版をしている。それも、編集者はInDesignを直接触らない。InDesignを触るのは印刷所の人間だ。ある編集者などは、「自分はコンピューターを触らない」と誇らしげに言うそうだ。そういう人は、紙に直接赤鉛筆などで組版の指示をして印刷所に投げる。

私からすると、GUIの組版ツールを使うのは同じ作業を何度も繰り返さなければならず極めて効率が悪いと思うのだが、印刷業界は不思議なものだ。

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

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

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

2016-04-06

Vim風のテキストエディターvis

martanne/vis: a vim like text editor

1%のコードで80%のVimの機能を目標に開発されているVim風のテキストエディター。

GUIとマウスのサポートがない以外は興味深い。

2016-04-04

アメリカ合衆国政府が公金を投じて開発されたソフトウェアは自由ソフトウェアにする法案を公開

https://sourcecode.cio.gov/SourceCodePolicy.pdf

Matthias Kirschner's Web log • US government commits to publish publicly financed software under Free Software licenses

アメリカ合衆国政府が、公金を投じて開発したソフトウェアは公共の財産であるのでデフォルトで自由なソフトウェアにする法案を公開している。

これは当然の話で、日本でも速やかに行うべきである。日本国政府が公金を投じて開発させるソフトウェアは自由なソフトウェアとすべきであって、プロプライエタリなソフトウェアの納品は禁止されるべきである。当然、WindowsやMac OS XなどのOSは国家に納品するには適さないOSである。

物理法則が同じかつ1900年ぐらいの科学レベルの異世界にタイムリープした現代人は現代の進んだ科学知識を活用して異世界チート主人公系ラノベのごとくになれるか

いかのような問題提起を考察したい。

なるほど、とても興味深い設定である。これについてできる限り考察してみよう。

異世界チート主人公系ラノベというジャンルがある。一個の現代人の主人公が常識や物理法則の違う異世界に飛ばされて、世界の差異を利用して有意に立つという筋書きの物語である。主人公はどこにでもいる一般人、それも無職とか低賃金有期雇用者とか、社会的弱者であることも多い。

ここでは2016年の人間が1900年に飛ばされて、科学知識の差を利用して活躍する筋書きである。活躍する上で、理解がクソなために科学の発展を阻害するというオチまで付けなければならない。

しかし、実証主義として考えれば、実際に観測可能な現象と一致する結論は、たとえ仮説が間違っていたとしても、科学の発展にはもたらす害悪よりも利益のほうが大きいのではないか。たとえばニュートンは筋金入りの神秘主義者で、現代の常識から考えれば非科学と迷信に凝り固まった人間ではあるが、ニュートンは確実に科学の発展に寄与している。

さて、まず1900年の科学水準について確かめてみよう。ひとまず1900年の日本語版のWikipediaを確認してみる。

1900年 - Wikipedia

  • 1月2日 - 初の電気バスがニューヨーク市で開業
  • 4月11日 - 米海軍が初の潜水艦ホーランド (潜水艦) を取得(就役10月12日)
  • 5月1日 - 東京電気鉄道(後の都電)設立
  • 5月29日 - 米国オーチス・エレベーター社がエスカレーターを商標登録
  • 7月2日 - ツェッペリン(水素ガスによる飛行船)が初飛行(ボーデン湖)
  • 7月19日 - パリ万国博覧会会期中にパリの地下鉄が開通
  • 8月8日 - 国際数学者会議にて、ヒルベルトの23の問題のうちの10題が公開される
  • 9月11日 - 日本初の自動公衆電話が東京の新橋駅と上野駅、熊本市内に設置

後にガンマ線と名付けられる放射線をポール・ヴィラールが観測したのも1900年である。

元素の発見もかなり進んでいて、放射性の元素もかなり発見されていたし、非放射性の元素はほとんど発見されていたし、未発見のものも発見は時間の問題であった。

なるほど、1900年の科学水準というのは、すでに電気バス、潜水艦、電車、エスカレーター、飛行船、地下鉄、公衆電話が存在していたどころか実用化もされていて、かつ数学もだいぶ進んでいたし、放射線の理解も進んでいたし、元素も安定したものはほとんど発見されていた。

さて、困った。1900年は思ったよりも科学水準が高い。例えば筆者程度の人間が1900年に飛ばされても、現代の科学知識を用いてチート主人公になることはできない。

ひとつ考えられるのは、この頃の一般大衆の科学水準はまだ低く、宗教や迷信が強く信じられていて、現代の進んだ心理学を元に大胆に振る舞えば、新興宗教とかネットワークビジネスの開祖としてそれなりに活躍できるのかもしれないし、「まっとうな科学の発展を阻害」するというもうひとつの目的も達成できるのかもしれないが、そういうことができる人間は現代でも新興宗教とかネットワークビジネスの開祖になれるだろう。そして、後述する言語の違いにより、この方法によるチート主人公となるのも難しいのである。

2016年と1900年で大きく違うのは、言語と人権である。この差は、おそらく主人公にはチートどころかハンディキャップになるであろう。

1900年の日本語は、現代と発音が異なる。2016年の主人公が音声学と日本の方言の考古学を専攻していて、かつ発音の実践を積んでいない限り、話し言葉による日常会話は困難であろう。1900年の価値基準で判断すると、主人公は実質的に失語症になってしまう。

書き言葉の差はもっと難しい。主人公が古文漢文に加えて草書体を相当に深く学んでいない限り、1900年の日本社会では文盲の扱いを受ける。当時は、ラテン語の読み書きができないものは論文すら読めずに、科学の世界に足を踏み入れることさえできない。文章で科学知識を伝えられなければ、いかに2016年の第一線の科学知識を持っていいようと無力である。英語はまだ世界共通語の地位を確立しておらず、ドイツ語やフランス語も科学の世界ではまだ強い力を持っていた。

たとえ筆者が2016年の最新の科学技術の知識を持っていて1900年において文書で書き残したとしても、その内容の解読には長い年月がかかり、功績が理解されるのは主人公の死後50年以上かかるであろうし、その頃には主人公の書き残した科学技術は独立して発見されているであろうから、社会への影響は、一部の歴史学者の混乱を除いて、良くも悪くも与えないだろう。

1900年においては、人権はかなり軽視されていた。たとえば1900年の1月23日には、光明寺村女工焼死事件が起こっている。これは織物工場で働く労働者の寄宿所が火事になったのだが、当時の慣習として、労働者の逃亡を防止するために、寄宿所の窓は鉄格子の上、ドアが施錠されていたから、労働者は逃げられなかったのだ。

リンカーンによる奴隷解放宣言は1862年であったが、アメリカ合衆国において黒人が選挙権を実際に行使できるようになるのは1971年からであった。

これを考えると、1900年に飛ばされた主人公は意思疎通ができず知的障害とみなされ、日銭を稼ぐために奴隷のような劣悪な労働環境に身をやつすことになるだろうと予想できる。

考察結果として、1900年の科学水準はかなり高く、2016年の一般人程度があやふやな科学知識を振りかざした程度では、異世界召喚系ラノベのような活躍はできないことが判明した。

2016-04-01

C++標準化委員会の文書: P0200R0-P0209R0

P0200R0: A Proposal to Add Y Combinator to the Standard Library

lambda式で再帰できるようにするY Combinbatorライブラリの提案。

int main()
{
    auto gcd = std:y_combinator( []( auto gcd, int a, int b ) -> int
        {
            return b == 0 ? a : gcd( b, a % b ) ;
        } ) ;

    std::cout << gcd( 20, 30 ) << std::endl ;
}

実装例

template < typename Fun >
class y_combinator_result
{
    Fun f ;
public :
    template < typename T >
    explicit y_combinator_result( T && fun )
        : f( std::forward<T>(fun) )
    { }

    template < typename ... Args >
    decltype(auto)
    operator () ( Args && ... args )
    {
        return f( std::ref(*this), std::forward<Args>(args)... ) ;
    }
} ;

template < typename Fun >
y_combinator_result<std::decay_t<Fun>> y_combinator( Fun && fun )
{
    return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun)) ;
}

[PDF] O0201R0: A cloning pointer-class for C++

コピー時にポインターの参照先をディープコピーするclone_ptrの提案。

int main()
{
    auto p1 = std::make_clone_ptr<int>(42) ;
    auto p2 = p1 ;
}

これは、以下のようなコードと同じ意味になる。

int * p1 = new int( 42 ) ;
int * p2 = new int( *p1 ) ;
delete p2 ;
delete p1 ;

また、clone_ptrは初期化時に渡されたmost derived typeによるポリモーフィックな型のディープコピーや破棄が正しく行える。


struct Base
{
    virtual void f() = 0 ;
    ~Base() { } // virtualデストラクターではない
} ;
struct Derived
{
    void f() override { }
    Derived() { }
} ;

// 実行時型
clone_ptr<Base> p1( new Derived() ) ;
auto p2 = p1 ;

// ディープコピーが行われる
assert( p1.get() != p2.get() ) ;
// Baseではなく実行時の型であるDerivedとしてコピーが行われる
assert( dynamic_cast< Derived * >(p2.get() != nullptr )

// p1, p2の破棄では、Derivedのデストラクターが呼ばれる

shared_ptrと同じだ。

コピー時にディープコピーを行うクラスのデータメンバーとして生のポインターの代わりに安全に使えるので入るべきだ。

A Proposal to Add Constexpr Modifiers to Functions in <algorithm> and <cstring> Headers

<algorithm>と<cstring>をconstexpr対応にする提案。イテレーターのconstexpr化は別の提案で行う。

<algorithm>をconstexpr化する提案。多くのアルゴリズムは<cstring>に依存しているので、<cstring>もconstexpr化する。

std::memcpyやstd::memmoveは、void *型の引数を取るので、本来constexpr化できないのだが、constexpr化しないとライブラリ実装はcompiler intrinsicsを使うだけなので、constexpr化する。

P0203R0: Considerations for the design of expressive portable SIMD vectors

SIMD型の提供に関する考察。

P0205R0: Allow Seeding Random Number Engines with std::random_device

乱数エンジンをrandom_deviceで初期化できるようにする提案。

現状では、random_deviceからビット列を手動で取り出して乱数エンジンに食わせてやらなければならないが、乱数エンジンの内部状態が何ビットなのか得る方法がないため、適切な初期化が移植性の高い方法で書けない。

これは当然入るべきだし、そもそも最初から入っているべき機能だ。

P0206R0: Discussion about std::thread and RAII

threadのデストラクターが実装された時に、threadがjoinableであると、terminateが呼ばれる。これは様々な問題を引き起こす。しかし一方で、この挙動のほうが好ましい場合もある。

この文書は、threadのデストラクターは自動的にjoinを呼ぶ変更か、自動的にjoinを呼ぶ別のthread型を追加する文面案を提示している。

既存のコードの挙動を変えないために別の型にすべきだろう。

P0207R0: Ruminations on lambda captures

lambada式で値によるデフォルトキャプチャー[=]が使われた場合、クラスのメンバーはthisポインター経由ではなく、値によるキャプチャーになるように挙動を変更するとどうなるかを考察。

この文書は、既存の挙動は変えないことを推奨している。

筆者は変えるべきだと思う。

[PDF] P0208R0: Copy-Swap Helper

強い例外安全を実現するために、まずオブジェクトをコピーして改変し、改変が例外を投げなければswapする。改変が例外を投げた場合元のオブジェクトは変更されないという処理を行うヘルパー関数の追加。

文面案のcopy_swap_helperの宣言が間違っている気がする。

[PDF] P0209R0: make_from_tuple: apply for construction

tupleの各要素をコンストラクターに渡してオブジェクトを構築してくれるmake_from_tupleの提案。

以下のように使う。

struct X
{
    X( int, double, std::string ) ;
} ;

auto t = std::make_tuple( 1, 2.0, std::string("3") ) ;

auto x = std::make_from_tuple<X>( t ) ;
// 以下と同じ
// auto x = X( get<0>(t), get<1>(t), get<2>(t) ) ;

すでにtupleの各要素を関数の引数に渡してくれるapplyがあるが、

void f( int, double, std::string ) ;

std::apply( t, f ) ;

make_from_tupleはそのオブジェクト構築版と言える。

同様にして、placement newしてくれるuninitialized_construct_from_tupleがある。

alignas(X) char buf[sizeof(X)] ;
X * ptr = std::uninitialized_construct_from_tuple<X>( buf, t ) ;

実装は以下のようになる。

template < typename T, typename Tuple, std::size_t ... I >
T make_from_tuple_impl( Tuple && tuple, std::index_sequence<I ... >  )
{
    return T( std::get<I>( std::forward<Tuple>(tuple) )... ) ;
} ;

template < typename T, typename Tuple >
T make_from_tuple( Tuple && tuple )
{
    return make_from_tuple_impl<T>(
        std::forward<Tuple>(tuple),
        std::make_index_sequence<
            std::tuple_size_v< std::decay_t<Tuple> >
            >()
        ) ;
}

ドワンゴ広告

Ubuntu On Windowsでドワンゴ社内の支給PCの勢力図が塗り替えられそうな気がするが、いい加減に支給PCのWindowsぐらい最新にするべきだと思うしGNU/LinuxをOSの候補に加えるべきだ。

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

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

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

Linuxにleftpad()というシステムコールを入れる提案

LKML: Richard Weinberger: New syscall: leftpad()

Linuxカーネルに興味深い日付でleftpad()というシステムコールが提案されている。

最近のnode.js業界の事件を振り返るに、leftpadのような基本的なアルゴリズムの依存はソフトウェアを脆弱にすることが判明した。ledpad[原文ママ]を提供するnode.jsパッケージが消失し、多くのソフトウェアが動かなくなった。

この事件に注目すると、node.jsベースのソフトウェアがLinuxの「ユーザースペースは壊さない」原則に将来的に頼ることができるので、このような機能を提供するのはカーネルの役目であるという結論に至った。

glibcとAndoid[原文ママ]のbionicは、早急にこの新しいシステムコールのラッパー関数を提供してくれることを望む。

leftpadをカーネルに入れたのはLinuxの安定したABIという理由だけではなく、パフォーマンス上の理由もある。

ご存知のように、カーネルでは、すべてが高速でかつ優れている。leftpadには大勢の利用者がいるので、可能な限り高速でなければならない。また、この新しいシステムコールはleft-pad.ioのようなサービスをより高速に安定して提供するのにも使うことができる。leftpad()システムコールが十分に利用された場合、npm()という、カーネルモジュールがnode.jsでよく使う新しい機能を登録できる、ioctl()のように機能する汎用的なシステムコールを付け加えるのも手だ。そのような機能としては、is_array()やis_int()が挙げられる。

[leftpad()システムコールをLinuxカーネルに追加するパッチ]

これを受けて、以下のような返信が行われている。

動いた。このシステムコールの重要性は筆舌に尽くしがたい。提案と実装してくれてありがたい。

パッチを提出する時はcheckpatch.plにかけてくれ。

これはよさそうだが、他のarchに対応させた上で、適切なメンテナーをCCに加える必要があるな。

これはよさそうだが、可能な限り高速にするために、無駄な範囲外チェックなどの分岐は全部除去したほうがよいし、ユーザーのメモリーに直接書き込むことで、無駄なcopy_from/copy_toを除去すべきだ。これにより、遅いkmallocも除去できる。

文章には注意を払ってくれ[ledpadとandoidのtypoの指摘]

参考: 本の虫: npmからkikとその他諸々が消されたまとめ

2016-03-30

C++標準化委員会の文書: P0190R0-P0199R0

[PDF] P0190R0: Proposal for New memory order consume Definition

memory_order_consumeの定義を変更する提案。RCUだけではなくGCなどにも利用できるようにする。Linuxカーネルでも使えるようにする。

[PDF] P0192R0: Adding Fundamental Type for Short Float

32bit以下のサイズのshort float型の追加の提案。

16bit浮動小数点数は機械学習や画像処理の分野で広く使われるようになっている。IEEE 754-2008では2進数16bitのフォーマットが定義されている。今のARMはネイティブにサポートしている。IntelのCPUでもサポートする計画がある。GPUでは、OpenGLが16bit浮動小数点数を規定している。OpenEXRではfloatの半分のサイズの浮動小数点数を組込型同様に扱えるライブラリがある。nVidiaのCUDAでは16bit浮動小数点数行列があるが、C++規格に存在しないために独自規格になっている。GCCはIEEEやARMのサポートのために__fp16型がある。LLVMにもhalf型がある。

16bit浮動小数点数型は現実の需要があるので、C++標準は早急に取り入れるべきであるとする。

型はshort floatで、浮動小数点数リテラルのサフィックスはsもしくはSだ。


short float s1 = 1.0s ;
short float s2 = 1.0S ;

これは早く入るべきだ。

P0193R0: Where is Vectorization in C++‽

C++に手動のベクトル処理を淹れる方法についての考察。ライブラリベースで入れることを検討している。具体的な話はあまりない。

[PDF] P0194R0: Static reflection (revision 4)

静的リフレクション機能の提案。

この提案では、宣言に何らかの演算子を適用すると、メタオブジェクトという型が生成され、その型を用意された特別なtraitsに渡すことで、名前や型などの詳しい情報を得ることができる。

P0195R0: Modernizing using-declarations

using宣言をpack展開に対応させる提案。

例えば、今提案中のoverloadは、

template< typename Head, typename ... Rest >
struct overloader : Head, overload< Rest... >
{
    using Head::operator() ;
    // コンストラクターなど
} ;

template < typename T >
struct overloader< T > : T
{
    using T::operator () ;
} ;

template < typename ... Types >
constexpr auto make_overloader( Types && ... args )
{
    return overloader< Types ... >( std::forward<Types>...) ;
}

のように再帰的に書かなければならない。これは非効率的だ。

再帰的に書かなければならない理由は、using宣言がパック展開に対応していないからだ。対応していれば以下のように書ける。

template < typename ... Types >
struct overloader : Types ...
{
    using Types::operator() ... ;
} ;

確かに便利だが、利用方法は限られる気がする。あって困ることはないだろう。

[PDF] P0196R0: A generic none_t literal type for Nullable types

型none_tとその値noneの提案。

optionalやanyといったライブラリでは、何も値が入っていないnullな状態になり得る(nullable)。各ライブラリごとにnullを表す別々の型を定義して使うのは冗長であるし、使い勝手も悪い。そこで、nullを意味する共通の型を定義しようという提案。これでジェネリックなコードはnullableな型に対してnullが入っているか確認する場合や、nullを入れる場合、単一の型を扱うだけで良くなる。

これも最近流行りのボキャブラリー型だ。入るべきだろう。

[PDF] P0197R0: Default Tuple-like Access

tupleのようなユーザー定義クラスに対して、tupleのようなアクセス(tuple_size, tuple_element, get)を書くのは面倒だ。そういうアクセスはコンパイラーが自動で生成すればいい。この文書は、tupleのようなアクセスをデフォルトで自動で生成する提案だ。

例えば以下のようなクラス、

struct X
{
    char m1 ;
    short m2 ;
    int m3 ;
} ;
X x{ 1, 2, 3 } ;

に対して、以下のようなtuple風アクセスが何もせずとも自動的に生成される。


tuple_size<X>::value ; // 3
tuple_element< 1, X>::type ; // short
get<2>( x ) ; // int型の値3
get<char>(x) ; // char型の値1

public非staticデータメンバーに対するtuple風アクセスが自動生成される。

protected, privated, virtualな基本クラスがない場合、基本クラスも再帰的に探される。

template  < typename Head, typename ... Rest >
struct X : X< Rest ... >
{
    Head m ;
    X( Head && head, Rest && ... rest )
        : X< Rest ... >( std::forward< Rest >( rest ) ... ),
            m( std::forward<Head>(head) )
    { }
} ;

template < typename T >
struct X<T>
{
    T m ;
    X( T && t )
        : m( std::forward<T>(t) )
    { }
} ;

X< char, short, int > x{ 1, 2, 3 } ;

tuple_size<X>::value ; // 3
tuple_element< 1, X>::type ; // short
get<2>( x ) ; // int型の値3
get<char>( x ) ; // char型の値1

いわば簡易的な静的リフレクションで、シリアライゼーションなどの用途に使えるだろう。ちなみに、提案はConcept TSに依存しているが、見た限り、コンパイル時チェックに使っているだけで、Concept TSの依存を取り除くのは可能のようだ。

いまのConcept TSには依存しないでほしい。

[PDF] P0198R0: Default Swap

クラスに対してデフォルトのswapを自動生成する提案。コンパイラーはデフォルトのスワップを生成する。デフォルトのswapはメンバーごとのswapを行う。

struct X
{
    int m1 ;
    std::string m2 ;
    std::array<int, 10> m3 ;
} ;

void f( X & a, X & b)
{
    // メンバーごとの効率的なswapが行われる
    swap( a, b ) ;
}

std::swapはムーブ可能な型に対しては効率良く動くが、std::arrayのような、ムーブをサポートできない型には効率が悪い。std::arrayのようなクラスは、メンバーごとのswapを行うと効率が良い。そのようなコードは単調で機械的に生成できるので、デフォルトで生成する。swapはfriendなフリー関数として扱われる。

この変更の背景には、swapはコピーやムーブと同じぐらい根本的な操作であるという思想がある。

これは入ってほしい。

[PDF] P0199R0: Default Hash

P0029R0では大抵の型を突っ込めるhash_combineが提案されている。これを使えば、クラス保持する状態のうち、比較に関係のある情報を全部突っ込めばハッシュ計算が素人でも簡単に書けるようになる。問題は、そのようなボイラープレートコードを書くのはダルいということだ。

そこで、そのようなボイラープレートコードをデフォルトで生成されるようにする提案。

P0029とともに入ってほしい提案だ。

ドワンゴ広告

今日は夕方から歯医者だったのでさっさと帰宅した。

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

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

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

WindowsにLinuxサブシステムを載せてUbuntuのユーザースペースが動く未来が来る?

​Microsoft and Canonical partner to bring Ubuntu to Windows 10 | ZDNet

詳しいことは明日発表されるということで、未だに公式の確証はないのだが、MicrosoftとCanonicalが提携してUbuntuをWindowsに持ってくるという話が上がっている。

現在予測されている内容では、これは単にWindows上で動く仮想環境でUbuntu GNU/Linuxを動かすという話ではなく、WindowsにLinux互換サブシステムを実装して、その上でUbuntuのGNU/Linux上で動くユーザースペースをそのまま持ち込むのではないかという憶測が出ている。つまり、aptでパッケージを管理してbashが使えてその他諸々のUbuntuのユーザースペースのCLIツールが全部使えるということだ。

これは、技術的に可能であろうが、Windowsに十分に互換性のあるLinux互換サブシステムを実装するのは不毛なほど金と労力がかかるだろう。

この憶測が正しいとして、どこまで実装するのかも気になる。CLIツールが動く程度だろうか。X.org互換か、あるいはX.orgが動くまで実装するのだろうか。

Linux互換サブシステムを実装する上で一番だるいのはなんだろうかと考えたところ、システムコールではioctlが一番だるいのではないかと思った。/procと/devもサポートしないと大抵のGNU/Linuxユーザースペースのプログラムは動かないので、やはりダルいだろう。

そしてもうひとつ気になるのが、ターミナルエミューレーターだ。まさかcmd.exeではあるまいな。せっかくのGNU/LinuxユーザースペースCLIプログラムが全部動いたとしても、端末がcmd.exeならば全てが台無しだ。

ということを考えると、やはりGNU/Linuxユーザースペースのターミナルエミューレーターも使いたくなり、ということはやはりX.orgが必要になる。

もうひとつの可能性として、Linuxカーネルを使うという手がある。ただ、これはGPLを考えるとありえないように思う。

何にせよ、そこまでしてGNU/Linuxのユーザースペースのツールを使うぐらいなら、最初からGNU/Linuxをネイティブにインストールしたほうがよい。

2016-03-29

C++標準化委員会の文書: P0174R0-P0189R0

P0174R0: Deprecating Vestigial Library Parts in C++17

標準ライブラリの一部をdeprecated扱いとする提案。

以下のライブラリのdeprecated扱いが提案されている。

std::iteratorは基本クラスとして使い、イテレーターの要件を満たすためのネストされた型名をわざわざ手動で定義する手間を省いてくれる。

しかし、本当に手間を省けるかというと疑問だし、クラステンプレートから非修飾名として使うと、依存名ではない問題が発生するので、わかりにくい。たとえば、以下のコードがエラーになる理由は、とてもわかりにくい。

#include <iterator>

template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
   value_type data;  // エラー、value_typeが見つからない 
};

maptとmultimapのvalue_compare。

mapとmultimapの実装には使えないし、ユーザーに使われている様子もない。

入力にイテレーターの片方しか取らない版のアルゴリズム(std::mismatchなど)は危険なのでdeprecated扱いにする。

std::allocatorの冗長なメンバー

allocator_traits経由で使うようになったので、冗長なメンバーはdeprecated扱いにする。

文書では、その他の候補としても、いくつかのライブラリを上げている。

vector<bool>は混乱のもとで廃止したいが、ストレージ効率のよい動的に確保されるストレージ上に構築されたビット列コンテナーの代替案が現在はない。

is_literal

is_literalには実用性がない。というのも、ジェネリックなコードで本当に知りたいのは、ある構築が定数初期化であるかどうかであって、型の構築方法の一つがリテラル型になるかどうかなどは実用性がない。

get_temporary_buffer/return_temporary_buffer

もともと不完全なままSTLに残っていたのがそのまま規格にも残ってしまった誰もまともに使っていないライブラリ。

raw storage iterator

今となってはあまり利用価値がない。

無駄な機能は積極的にそぎ落としてほしい。

P0175R0: Synopses for the C library

C++の規格にC言語のライブラリの宣言を追加する提案。今まではヘッダーファイルだけ参照していた。

ユーザーとしては特に変わることはない。

P0177R0: Cleaning up allocator_traits

allocator_traitsのpropagateがイマイチ理解できない理由がわかった。

propagateはアロケーターが状態を持っているかどうかを判別するのに使うのだが、コピー代入とムーブ代入とswapに対して状態があるかどうかを判定するようになっているので、2^3通りの組み合わせがある。当然、ライブラリ側も2^3通りの組み合わせに対処しなければならない。

しかし、現実的に考えれば、アロケーターは状態を持っているかいないかの2通りの場合しかないはずで、原稿の規格はおかしい。これを簡略化するために、既存のpropagate系の判定を全部deprecated扱いにして、単一のpropagateを追加する提案。

これは当然行われるべき変更だ。

P0178R0: Allocators and swap

コンテナーなどのアロケーターを使う型で、アロケーターが状態を持っていて、アロケーターのオブジェクトが等しくない場合、swapが未定義の場合について、それぞれ一時オブジェクトにムーブした上でムーブする方法を使うことで、未定義を回避するフリー関数swapの追加。

P0180R0: Reserve a New Library Namespace Future Standardization

コア言語に新しい機能が入り、ライブラリの設計方法に新しい手法が考案されていき、また現実の需要と事情が変化する中で、近い将来にC++の標準ライブラリには破壊的変更を伴う大幅な変更が必要になるだろう。そのために、新しい名前空間std2とisoを予約する提案。

死蔵されなければよいが。

Ordered By Default

setやmapは、要素の大小比較にoperator <を使っている。これは大抵の場合うまく行くが、世の中には数学的な大小比較を提供していない型も存在する。例えば、。std::complexだ。ただし、complexはsetやmapのための大小比較は提供できる。しかし、そのためには大小比較を定義した上で、比較子をコンテナーに渡してやらなければならない。

struct complex_order
{
    template < typename T >
    bool operator () ( std::complex<T> const & l, std::complex<T> const & r )
    {
        std::tie(l.real, l.img) < std::tie( r.real, r.img ) ;
    }
} ;

int main()
{
    std::set< std::complex<float>, complex_order > s ; 
}

いちいちコンテナに比較子を渡すのが面倒だ。lessを特殊化してやれば明示的に渡す必要はなくなる。

namespace std
{
    template < typename T >
    struct less< std::complex<T> >
    {
        bool operator () ( std::complex<T> const & l, std::complex<T> const & r )
        {
            std::tie(l.real, l.img) < std::tie( r.real, r.img ) ;
        }

    }
} ;

std::set< std::complex<float> > s ;

しかし、これではlessはoperator <を呼び出すものという既存のcontractがこわれてしまう。

そのため、ユーザーにカスタマイゼーションポイントとして、別のテンプレートを提供する。

template <typename T>
struct default_order {
   using type = std::less<T>;
};

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

template < typename Key, typename Compare = default_order_t<Key>,
            typename Allocator = allocator<Key> >
struct set ;

あとは、default_orderを特殊化するだけだ。

template < typename T >
struct default_order< std::complex<T> >
{
    using type = complex_order ;
} ;

この提案は、既存のコードのABI互換性を壊さない。

どんな問題でももう一段階のラッパーをかますことで解決できる。ただし、ラッパーが多すぎるという問題を除いては。

P0184R0: Generalizing the Range-Based For Loop

range-based for loopでイテレーターの先端と終端の型を別にできるように制限を緩和する提案。

Range TSは番兵という概念を導入している。番兵となるイテレーターは別の型でもよい。

struct range
{
    iter begin() const ;
    sentinel end() const ;
}

void f( range const & r )
{

    auto i = r.begin() ;
    auto e = r.end() ;

    for ( ; i != e ; ++i )
    {
        do_somethign( *i ) ;
    }
}

このようなrange型は、現在のrange-based forには渡せない。なぜならば、コード変換のルールが、イテレーターの先頭と終端の型が同じでなければならない制約になっているからだ。この制約をなくし、上のようなrangeをrange-based forに渡せるようにする変更。

適切な変更だ。

P0185R0: Adding [nothrow-]swappable traits (Revision 2)

std::is_swappable<T>, std::is_swappable_with<T, U>, std::is_nothrow_swappable<T>, and std::is_nothrow_swappable_with<T, U>と、その変数テンプレート版(名前が_tで終わるもの)をtype_traitsに追加する提案。

また、utilityにあるswapを、

void swap(optional<T>& rhs)
    noexcept(
        is_nothrow_move_constructible_v<T>
        && noexcept( swap(declval<T&>(), declval<T&>()))
    );

にする。

いい変更だ。

P0186R0: Iterator Facade -

イテレーターを簡単に書けるライブラリの追加。

標準ライブラリに準拠するイテレーターを正しく書くのはボイラープレートコードが多すぎて面倒だ。そこで、このライブラリはC++17とConcept TSとRange TSがあれば簡単にイテレーターが書けるライブラリを提案している。

Concept TSもRange TSもしばらく入らないことを考えると、このライブラリも当分日の目を見ないだろう。

[PDF] P0187R0: Proposal of Bit­field Default Member Initializers

ビットフィールド付きのデータメンバーにデフォルトメンバー初期化しを書けるようにする提案。

struct X
{
    int data : 6 = 42 ;
} ;

文法上の曖昧性を解消してパースを簡単にするために、初期化子には=しか使えない。そして、=の後には初期化子が続かなければならない。例えば{}は書けない。

まあ、いいのではないか。

[PDF] P0188R0: Wording for [[fallthrough]] attribute.

switch文のcaseラベルを通り抜けるのが意図的であると明示的に記述する[[fallthrough]]属性の文面案。

例えば以下のようなコードを書くと、

switch( n )
{
case 2 :
case 3 : // OK、特に何もない
    f() ;
    break ;

case 4 :
    g() ; // 警告、通り抜けてませんか?
case 5 :
    h() ;
}

最近のおせっかいなコンパイラーはcase 4でbreakを書き忘れていないかという警告をしてくる。もし、プログラマーの意図が、nが4の場合は関数gとhを両方呼び出し、nが5の場合は関数hのみ呼び出すというものであれば、上記のコードは正しい。そこで、プログラマーの意図をコード上で伝えるために、[[fallthrough]]を書くことができる。

case 4 : 
    g() ;
    [[fallthrough]]
case 5 :
    h() ;

いちいち書くのが煩わしい以外はいいか。

[PDF] P0189R0: Wording for [[nodiscard]] attribute.

関数の戻り値を使わないと警告される[[nodiscard]]属性の文面案。

// 失敗する可能性があるとても重要な処理
// 失敗した場合はfalseを返す
[[nodiscard]] bool very_important_operation() ;

int main()
{
    // 警告
    very_important_operation() ;
}

また、型に指定した場合、その型を戻り値として使うと、関数に[[nodiscard]]を指定した扱いになる。


[[nodiscard]] struct error_status { } ;
error_status f() ; // [[nodiscard]]がつく

これはC++17に入るコア言語機能の中でも最も一般に役に立つ機能だと思われる。

ドワンゴ広告

ドワンゴではとある一社員が個人的にお菓子神社という霊験あらたかな神社を開いており、参拝者も多い。筆者もポテトチップスという現世利益のために浄賽を投じようと思ったが、ポテトチップスは一袋335kcalもあり、ジョギング換算で5kmに相当し、脂肪換算で46gにあたるため、強い意志力を持ってやめておいた。

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

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

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