2015-10-29

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

P0040R0: Extending memory management tools

イテレーターを取り、イテレーターの範囲の未初期化のストレージに対して、構築や破棄をする関数destroy, uninitialized_move, uninitialized_move_n, uninitialized_value_construct, uninitialized_default_constructの追加。

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

template < typename ForwardIterator >
void destroy( ForwardIterator begin, ForwardIterator end )
{
    using type = iterator_traits<ForwardIterator>::value_type ;
    while ( begin != end )
    {
        begin->~type() ;
        ++begin ;
    }
}

P0041R0: Unstable remove algorithms

unstable_removeアルゴリズムの提案。

従来のeraseは、消した要素の穴を、後続の要素をシフトさせることによって埋める必要がある。これは、要素の順序を変えない安定した動作が要求されているためである。

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

// v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
std::remove( begin(v), end(v), 2 ) ;
// v = { 1, 3, 4, 5, 6, 7, 8, 9, ? }   

要素を一つづつコピー/ムーブして穴を埋める動作は、要素の具体的な型にもよるが、コストがかかる。

ここで、もし要素の順序を変える不安定な動作が許されるのであれば、末尾の要素で埋めるなどして、コピー/ムーブの回数を減らせる。

// v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
std::unstable_remove( begin(v), end(v), 2 ) ;
// v = { 1, 9, 3, 4, 5, 6, 7, 8, ? }   

そこで、unstable_removeの提案となる。他にも、unstable_remove_if, unstable_remove_copy, unstable_remove_copy_ifも追加される。

提案では拡張案として、メンバー間数版であるeraseにもunstable_eraseを加える案が考察されている。

P0042R0: std::recover: undoing type erasure

function, any, variant, optionalなど、C++にはtype erasureを使ったライブラリが多い。問題は、ライブラリごとに元の型を得る方法がバラバラで、全く統一されていないということだ。たとえば、functionはtargetメンバー関数を使うし、anyはany_castというフリー関数を使う。variantはstd::getをオーバーロードしていて、std::optionalは、型が入っていないとbad_optional_access例外を投げる。

今後、type erasureを使うライブラリが増えるたびに、bad_library_name_accessなる例外クラスが増えるのでは、ますます標準ライブラリを肥大化させるだけだ。元の型を得るという同じような処理は、共通の汎用的な方法で扱えるべきだ。

そのために、この提案では、ErasureClassコンセプトを定義し、type erasureを行うクラスが実装すべきメンバーの要件を定義している。

そして、ErasureClassコンセプトを使って元の型を取り出すフリー関数recoverが追加される。

void f() { }

int main()
{
    function< void () > a = &f ;
    std::experimantal::any b = &f ;

    auto c = a->target() ;
    auto d = any_cast< void (*)() >( b ) ;
}

このようにバラバラの方法で取り出していたのが、

auto c = std::recover<void (*)()>(a) ; 
auto d = std::recover<void (*)()>(b) ; 

このように統一化された方法で取り出すことができるようになる。型チェックに失敗すると、bad_recovery_access例外が投げられる。

[PDF注意] P0043R0: Function wrappers with allocators and noexcept

functionをアロケーターに対応させるにあたって、type erasureを使ってアロケーターを格納する方法を採用した。これは様々な問題を生む。たとえばnoexceptにできなくなる。

そこで、functionの挙動変更と、ひとつのアロケーターオブジェクトを要素であるfunctionに渡すfunction_containerを提案している。

文章がやたらと不親切で読みにくい上に、提案している機能が不必要に複雑で、一般人が使いこなせるとは思えない。

[PDF注意] P0044R0: unwinding_state: safe exception relativity

uncaught_exceptionsをdeprecatedさせて、新たにunwinding_stateを導入する提案。

uncaught_exceptionは、ハンドルされていない例外が存在するかどうかをbool値で返す。つまり、例外がthrowされたことによるstack unwindingが発生しているかどうかを調べることができる。これは、デストラクターの挙動を変えるのに使える。

struct X
{
    ~X()
    {
        if ( std::uncaght_exception() )
        {
            // 通常の破棄
        }
        {
            // do_somethingが例外を投げたので
            // stack unwinding中
        }
    }
} ;

int main()
{
    try {
        X x ;
        do_something() ;
    } catch ( ... ) { }
}

問題は、stack unwindingの最中にも、例外スコープは作成されるということだ。

struct Y
{

    ~Y()
    {
        if ( std::uncaught_exceptions() )
        {
            try {
                X x ;
                do_recovery_thing() ;
            } catch( ... ) { }
        }
    }
}

この場合は、通常のtryスコープを抜けたxの破棄であっても、xのデストラクターはstack unwinding中であると認識してしまう。

これを防ぐために、uncaught_exceptionsが追加された。これは、現在ハンドルされていない例外の数をint値で返す。

問題は、未ハンドルの例外の数を返すということは、現在の未ハンドルの例外数をどこかに保存しておいて、それを比較しなければならないということだ。

struct X
{
private :
    static int e ; // 別のところで書き込まれる
public :
    X() : e( std::uncaught_exceptions() ) { }

    ~X()
    {
        if ( std::uncaught_exceptions() == e )
        {
            // 通常の破棄
        }
        else
        {
            // stack unwinding中
        }
    }

} ;

uncaught_exceptionsを正しく使うには、このように例外が発生する前に例外数を記録しておいて、例外が発生しているかもしれない箇所で、前回の例外数と異なるかどうかを比較しなければならないのだ。

そもそも、例外数を返すというのは、Itanimu ABIに例外数を記録するためのグローバル変数があるからだ。他の実装も考えられる。例えば、ARM EHABIは、現在未ハンドルの例外をリンクリストで管理することを規定している。

現在の例外数を取得することに需要はない。需要は、現在stack unwinding中かどうかを判定することだ。そのため、例外ハンドルの状況が変わったかどうかだけを調べる方法があればよい。

そこで、unwindling_stateクラスが提案されている。このクラスは、非staticメンバーのガードオブジェクトとして使うことができる。

struct X
{
private :
    std::unwinding_state s ;
public :

    ~X()
    {
        if ( 1s )
        {
            // 通常の破棄
        }
        else
        {
            // stack unwinding中
        }
    }

} ;

unwinding_stateのコンストラクターは、現在のstack unwindingの状態を記録する。operator boolは、現在のunwindingがオブジェクト構築時に保存したunwindingと同一かどうかをboolで返す。

operator boolはexplicitとなっているので、lvalueとして使わなければならない。以下のような誤った記述はできない。

if ( unwinding_state() )

コピーやムーブは普通にできる。

[PDF注意] P0045R0: Overloaded and qualified std::function

オーバーロード可能なfunctionの提案。既存のstd::functionにVariadic Templatesで複数のシグネチャを指定可能にするというもの。

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

int main()
{
    std::function< void ( int ) , void ( std::string ) > f ;

    f = []( int ) { } ;
    f = []( std::string ) { } ;

    f = []( auto ) { } ;

    f( 0 ) ;
    f( std::string("hello") ) ;
}

これを実現するために、target型ごとにグローバルなtupleを作ってディスパッチさせる、いわゆるvtableを実装している。正直ついていけない。

しかし思うのだが、コア言語にあるvtableが非効率的なので独自vtableを自作しましたというのはなんだか本末転倒ではないか。もちろん、通常の関数ポインターまで含めたtype erasureを、本来その目的に設計されていなかった組み込みvtableで実装するので、そういう非効率さが発生するのだが。

P0046R0: Change is_transparent to metafunction

連想コンテナーでHeterogeneous lookupを実現するために、比較関数にis_transparentというネストされた型があるかどうかをヒントにしてきたが、これは使いにくいので、permits_heterogenous_lookupというtraitsを追加する提案。

正直すごく使いづらい。

P0047R0: Transactional Memory (TM) Meeting Minutes 2015/06/01-2015/09/21

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

P0048R0: Games Dev/Low Latency/Financial Trading/Banking Meeting Minutes 2015/08/12-2015/09/23

ゲーム開発、低レイテンシー、アルゴリズム取引、銀行に関する会議の議事録。

ドワンゴ広告

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

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

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

Visual StudioにClangフロントエンドがやってくる

22日に書いたのだがあげ忘れていた。

Microsoft promises Clang for Windows in November Visual C++ update • The Register

先月のCppConでMicrosoftが発表した内容によれば、Visual StudioにClangがやってくるそうだ。

Microsoftは独自のプロプライエタリなC++コンパイラーを開発しているが、将来、Visual StudioでClangが扱えるようになるそうだ。

現在、AndroidやiOS開発用には、Visual StudioでもGCCやClangが使えるが、Windows用にもClangが提供されるらしい。

MSのC++コンパイラーには、フロントエンド部分(パースして内部表現に変換)とバックエンド部分(内部表現からコード生成)があるが、Clangが使われるのはこの内のフロントエンド部分になる。ClangでLLVM IRを生成して、そこからMSのプロプライエタリなバックエンドが期待する内部表現フォーマットに変換して、コード生成は自前のプロプライエタリなコンパイラーで行うそうだ。

MS独自のプロプライエタリなTwo-phase lookupすらまともにできない規格違反のクソC++コンパイラーの開発も続行されるらしい。

ドワンゴ広告

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

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

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

ある程度自由なラップトップ、Novena

Novena: A Laptop With No Secrets - IEEE Spectrum

ある程度自由なラップトップを作ったそうだ。

ムーアの法則が破れてきた今となっては、小規模なハードウェア制作もやりやすくなっているとのこと。というのも、このプロジェクトがスタートしてから数年たっているが、当初選んだ40nmプロセスは、いまだにコストとパフォーマンスを天秤にかけてちょうどいい釣り合いがとれている。また、中国の製造業者も、少数製造にも興味を示しているとのこと。

できるだけファームウェアブロブの少ないパーツを選定したとのこと。CPUにはFreescaleのARMプロセッサー、i.MX6 SoCを選んだ。ファームウェアはROMに内蔵されているが、IntelのCPUと違い、アップデートできないし、かつ暗号化もされていないとのこと。

Freescaleの提供するパッチをLinuxのコード規約にあわせるなどして、Linuxカーネルの上流に採用させたとのこと。

内蔵GPUはプロプライエタリなバイナリブロブのドライバーを必要とする。このドライバーを使うと、Linuxカーネルのバージョンが固定されてしまう上に、ドライバー自体もクソで、浮動小数点演算をソフトウェアで行っているとのことだ。

そのため、内臓GPUは使わず、ソフトウェアですませる。このため、WMにはXfce4を使い、ディストロはDebianを使っているとのことだ。

気に入らないのは、FPGAが載っていることだ。FPGAのツールは不自由であるし、詳細はわからないが、もしそのような不自由なハードウェアがメモリにDMAアクセスできるようになっているのは危険だ。

どうもいまひとつ惜しいコンピューターだ。

2015-10-26

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

[PDF] P0030R0: Proposal to Introduce a 3-Argument Overload to std::hypot

C++11で追加されたstd::hypotに3引数版のオーバーロードを追加する提案。

std::hypot( x, y )は、\(\sqrt{ x^2 + y^2}\)を、計算過程でオーバーフロー、アンダーフローが発生しない方法で計算する関数だ。

hypotの応用方法として、二次元空間における2点間の距離の計算、\(\sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}\) に使える。

struct point
{ double x, y ; } ;

double dist( point a, point b )
{
    return std::hypot( a.x - b.x, a.y - b.y ) ;
}

しかし、多くの分野では、三次元空間における2点間の距離を計算、、\(\sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2 (z_q - z_2)^2}\)したいことがよくある。hypotは2引数なので、現状では以下のように使わなければならない

struct point
{ double x, y, z ; } ;

double dist( point a, point b )
{
    return std::hypot( a.x - b.x, std::hypot( a.y - b.y, a.z - b.z ) ) ;
}

hypotに3引数版のオーバーロードを追加すると、以下のように書ける。


std::hypot( a.x - b.x, a.y - b.y, a.z - b.z ) ;

論文では、Variadic templatesを利用した任意個の引数を取る汎用的な関数の提案も考えたが、そのような関数の利用例が明らかではないとして、今回の提案では3引数版のみにとどめたという。

P0031R0: A Proposal to Add Constexpr Modifiers to reverse_iterator, move_iterator, array and Range Access

array, reverse_iterator, move_iteratorをconstexprに対応させる提案。

P0032R0: Homogeneous interface for variant, any and optional

現在提案されているvariant, any, optionalには、機能は同じだがメンバー名や引数などが異なるメンバーがあるので、統一を図る。

P0033R0: Re-enabling shared_from_this

現行のenable_shared_from_thisの文面では、挙動が明確に規定されていないコードが存在してしまう。

enable_shared_from_thisは、shared_ptrで管理する型の基本クラスとすることで、shared_from_thisというメンバー関数を追加できる。このメンバー関数を呼び出すと、そのオブジェクトを所有している既存のshared_ptrが返される。以下のように使える。

// CRTPとして使う
struct X : public std::enable_shared_from_this<X>
{ } ;

int main()
{
    auto sp1 = std::make_shared<X>() ;

    // sp1と所有権を共有するshared_ptrが得られる
    auto sp2 = sp1->shared_from_this() ; 
}

ところが、現行の文面では、以下のようなコードの挙動が未定義になってしまう。

int main()
{
  struct X : public enable_shared_from_this<X> { };
  auto xraw = new X;
  shared_ptr<X> xp1(xraw);  // #1
  { // 破棄時にdeleteしないので安全
    shared_ptr<X> xp2(xraw, [](void*) { });  // #2
  }
  xraw->shared_from_this();  // #3
}

shared_from_thisの前提条件として、オブジェクトを所有するshared_ptrのオブジェクトが存在しなければならない。このコードでは、存在している。問題は、複数のshared_ptrが独立して存在しているということだ。ただし、後から構築される#2のオブジェクトのデリーターは何もしないので、このコードは二重にdeleteするという問題はない。すると、このコードは合法なのだろうか。

しかし、合法だとして、この場合はどちらのshared_ptrと所有権を共有するオブジェクトが返るのだろうか。#1だろうか、#2だろうか。

#1が返る場合、#2のshaared_ptrの構築時には、xraw->_weak_thisがアップデートされないことになる。#2が返る場合、アップデートされる。

問題は、shared_from_thisのpostconditionに照らし合わせると、どちらの挙動もweak_ptrがらみのpostconditionを満たせないので、規格上挙動が規定されていない。

さて、既存の実装であるDinkumware, GNU, LLVMの実装は、いずれも#2が_weak_thisをアップデートする挙動になっている。これは設計上意図的なものではない。

一方、Boostの実装では、ユーザーの意見を取り入れた結果、#2は_weak_thisをアップデートしない挙動に意図的にしている。つまり、一番最初に作られたshared_ptrと所有権を共有するshared_ptrを返す。

現在、既存の実装の挙動に依存したコードはなく、Boostの挙動の方が実際の需要があるため、Boostの挙動にあわせる変更を提案している。

また、この提案では、weak_ptrを得るweak_from_thisの追加も提案されている。

P0034R0 – Civil Time

軽量な日付ライブラリの提案。

Boost. Date Timeはあまりにも巨大すぎるし、作者が標準ライブラリに追加することに興味を示していないので、軽量な日付ライブラリを提案している。

このライブラリは、グレゴリオ暦以前の日付はtime_tのオーバーフロー、time_t以上の精度でうるう秒を扱うことは考慮しない。タイムゾーンが使える。

P0035R0: Dynamic memory allocation for over-aligned data

待望のオーバーアライメントしてくれる確保関数の提案。

C++の現行規格では、確保関数はオーバーアライメントする必要はない。例えば、floatのアライメントが4バイトで、SIMD命令の都合上、floatの配列を16バイトアライメントしたいとする。以下のようなコードを書いても、16バイトアライメントされる保証はない。

class alignas(16) float4 {
 float f[4];
};
float4 *p = new float4[1000];

C++の規格上は4バイトアライメントされれば十分なのだ。オーバーアライメントは規格上必須ではない。

シグネチャは以下のようになる。

namespace std {
    enum class align_val_t: size_t;
}
void* operator new(std::size_t size, std::align_val_t alignment);
void* operator new(std::size_t size, std::align_val_t alignment,
   const std::nothrow_t&) noexcept;
void operator delete(void* ptr, std::align_val_t alignment) noexcept;
void operator delete(void* ptr, std::align_val_t alignment,
   const std::nothrow_t&) noexcept;
void* operator new[](std::size_t size, std::align_val_t alignment);
void* operator new[](std::size_t size, std::align_val_t alignment,
   const std::nothrow_t&) noexcept;
void operator delete[](void* ptr, std::align_val_t alignment) noexcept;
void operator delete[](void* ptr, std::align_val_t alignment,
   const std::nothrow_t&) noexcept;

P0036R0: Unary Folds and Empty Parameter Packs (Revision 1)

folding expressionに空のパラメーターパックを指定した時のフォールバックを、operator &&, operator ||, operator , だけに留める提案。

デフォルトで0が変えるとまずい場合がある。

P0037R0: Fixed_Point_Library_Proposal

固定少数点ライブラリの提案。

template < class ReprType, int Exponent >
class fixed_point ;

ReprTypeは内部でつかう整数型で、Exponentは、ビットを指定された数だけシフトする。fixed_pointの精度は、pow(2, Exponent)であり、最小値と最大値は、pow(2, Exponent)にstd::numeric_limites<ReprType>::min()/max()を掛けた値になる。

Exponentを指定するのは面倒だ。固定少数は、基数ビット数と少数ビット数を記述することで指定できる。プログラマーの多くはこの記述方法を好む。

そこで、fixed_pointのエイリアスが用意される。

template <unsigned IntegerDigits, unsigned FractionalDigits = 0, bool IsSigned = true>
    using make_fixed ;

template <unsigned IntegerDigits, unsigned FractionalDigits = 0>
    using make_ufixed ;

例えば、8bitの符号なしの固定少数で、基数と少数のビット数にそれぞれ4ビット割り当てたい場合は、

make_ufixed<4, 4> value{ 15.9375 } ;

32bit、符号あり、基数が2ビット、少数が29ビットにしたい場合は、

make_fixed<2, 29> value { 3.141592653 } ;

固定少数と組み込みの整数型は相互に明示的に変換できる。

丸め誤差は発生する。

make_ufixed<4, 4>(.006) == make_ufixed<4, 4>(0)

このコードは丸められた結果trueとなり得る。

整数に普通に使える演算子は固定少数にもオーバーロードされていて普通に使える。シフト演算子と比較演算子以外では、二項演算子は固定少数同士や、固定少数と他の演算型を組み合わせてオペランドに取れる。

組み合わせが同じ固定少数型ではない場合、簡単なプロモーション風のルールによって、戻り値の型が決定される。

  1. どちらの実引数も固定少数の場合、大きなサイズの型が選ばれる。どちらか片方が符号付きならば、符号付きになる
  2. どちらかの実引数が浮動小数点数型の場合、結果の型は入力と同じかそれ以上大きい、最小の浮動小数点数型になる
  3. どちらかの実引数が整数型の場合、結果は他方の固定少数型になる

make_ufixed<5, 3>{8} + make_ufixed<4, 4>{3} == make_ufixed<5, 3>{11};  
make_ufixed<5, 3>{8} + 3 == make_ufixed<5, 3>{11};  
make_ufixed<5, 3>{8} + float{3} == float{11};  

提案では、このプロモーションルールの理由を、挙動を簡単に推測できるためとパフォーマンス上の理由から、各ルールについて以下のように説明している。

  1. 固定少数のみが使われていた場合に、最小の計算のみが行われることを保証する。
  2. 型を混ぜた演算のプロモーションルールをまねた。固定少数の範囲から外れるようなexponentを持つ値も作り出せるようにし、浮動小数点数から整数へのコストのかかる変換を避ける
  3. 入力として与えられた固定少数型を維持する。処理に重要なのは意図的に固定少数型である

シフト演算子は右辺に整数型を取り、オーバーフロー、アンダーフローしない新しい型を返す。

比較演算子は、プロモーションルールにしたがって入力を共通の型に変換した上で、比較して、結果をtrueかfalseで返す。

符号付きと符号なしの固定少数のオーバーフローは、未定義の挙動となる。符号なしの整数型のオーバーフローの挙動が規定されている基本型とは異なる。

// オーバーフローの例
make_fixed<4, 3>(15) + make_fixed<4, 3>(1)

アンダーフローが発生して精度が失われることは許容されている。


make_fixed<4, 3>(15) + make_fixed<4, 3>(1) ;

この結果は7になるが、これは許容されている。

ただし、すべてのビットがアンダーフローによって失われた場合、その値は「フラッシュされた」状態になり、未定義の挙動となる。

固定少数の精度を上下させるpromote/demote関数がある。これは、基数部と小数部のビット数をそれぞれ、2倍、1/2倍する。

// make_fixed< 4, 4 >
promote( make_fixed< 2, 2 >(1) ) ;
// make_fixed< 2, 2 >
promote( make_fixed< 4, 4>(1) ) ;

オーバーフローを防ぐために精度を上げつつ計算する関数が用意されている。

単項演算子としては、trunc_reciprocal, trunc_square, trunc_sqrt, promote_reciprocal, promote_square

二項演算子としては、trunc_add, trunc_subtract, trunc_multiply, trunc_divide, trunc_shift_left, trunc_shift_right, promote_add, promote_sub, promote_multiply, promote_divide

trunc_は、入力よりも大きくはない結果を返すが、exponent部分をオーバーフローを避けるために変更される。

promote_は、オーバーフローとアンダーフローが起きないほど十分に大きな型を結果として返す

_multiplyと_squareは、64bit型には提供される保証がない。

_multiplyと_squareは、入力が最小負数である場合、未定義の挙動となる。

_squareは符号なし型を返す

_divideと_reciprocalは、ゼロ除算チェックは行わない

trunc_shift_は、最初の入力と同じ型を返す。

関数はまだ追加される余地がある。

P0038R0: Flat Containers

Boost.ContainerにあるFlat Associative Container(flat_map, flat_set, flat_multimap, flat_multiset)の追加。

フラット連想コンテナーとは、従来の連想コンテナーであるmapやsetのように、キーと対応する値をもっていて、キーによって値を高速に検索できる特性を持つ。従来のノードベースの連想コンテナーと違い、連続したストレージ上に要素が確保される。

実装方法は2つある。ひとつは要素を常にキーでソート済みにしておくこと。もうひとつはヒープ構造を用いること。Boostの実装はソートを使っている。ヒープを使った実装はキャッシュのローカル性を保ちやすいので、理論上優れた実装であるとされ、会議では関心が高かったが、実装経験が少ないため、さらなる検証が必要であるとしている。

P0039R0: Extending raw_storage_iterator

raw_storage_iteratorを改良する提案。

raw_storage_iteratorにムーブ代入演算子を追加し、ムーブに対応させる。

raw_storage_iteratorを作るのは面倒なので、factory関数を追加する。

template<class T>
auto make_storage_iterator( T&& iterator)
{
 return raw_storage_iterator<std::remove_reference<T>::type, decltype(*iterator)>( std::forward<T>(iterator));
}

raw_storage_iteratorの目的は、主にplacement newで使うためだが、placement newの文法はraw_storage_iteratorをサポートしていない。これを直接サポートする。

template<class T, class U>
void* operator new(size_t s, raw_storage_iterator<T,U> it) noexcept
{
 return ::operator new(s, it.base() );
}

template<class T, class U>
void operator delete ( void* m, raw_storage_iterator<T,U> it) noexcept
{
 return ::operator delete(m, it.base() );
}

ドワンゴ広告

この記事はドワンゴ勤務中に書かれた。来月は有給を取りまくる必要のある事情がある。

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

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

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

2015-10-20

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

P0021R0: Working Draft, C++ Extensions for Ranges

Range TSのドラフト。コンセプトを使ったRangeライブラリの提案。

イテレーターのペアを扱うよりも、Rangeという単位で簡単に扱うことができる。

ユーザーにわかりやすい恩恵としては、algorithmにイテレーターのペアではなくコンテナーを渡せるようになる。単に使う際にはコンセプトを意識する必要はない。

P0022R0: Proxy Iterators for the Ranges Extensions

vector<bool>のようなプロクシーイテレーターをRangeに対応させるためにRange提案を修正する提案。既存のiter_swapに加えて、iter_moveを追加して、プロクシーイテレーターのためのカスタマイゼーションポイントとする。

コンセプトにマップがあればもっと楽になるのに。

P0024R0: The Parallelism TS Should be Standardized

既存のalgorithmを並列実行させ、また並列計算のためにnumericライブラリを追加するParallelism TSを、標準規格に取り入れるべきだという提案。

Parallelism TSの実装経験は豊富であり、C++17に加えるに足る。

Parallelism TSは、たとえば、以下のようにvector<int>の各要素に処理を加えるコードがある。

void process_data( std::vector<int> const & data )
{
    std::for_each( std::begin(data), std::end(data),
        []( auto e ) { DoSomething(e) ; } 
    ) ;
}

このコードは、以下のように変更を加えるだけで、並列実行させることができる。


std::for_each( std::par, std::begin(data), std::end(data), ...

このように、既存のalgorithmに並列実行版のオーバーロードを加える。また、並列計算用のnumericが用意されている。

すでに、Microsoft, HPX, Codeplay, HSA, Thibaut Lutz, NVIDIAが独立してParallelism TSを公に実装している。

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

標準ライブラリにclamp( value, min_value, max_value )を追加する提案。valueがmin_valueより小さいならmin_valueを、max_valueより大きいならmax_valueを、そうでなければvalueを返す。

比較関数をとるオーバーロード、clamp( value, min, max, comp)も追加される。

P0026R0: multi-range-based for loops

Range-based forの拡張提案。

range-based forはコンテナーの各要素に対する処理を簡単に書くことができる。

std::vector<int> v ;

for ( auto && elem : v )
{
    DoSomething( elem ) ;
}

しかし、現実では、複数のコンテナーのそれぞれの各要素を先頭から同時にアクセスしたいことがよくある。そういう場合、古典的なforループを使わざるを得ない。

std::vector<int> v1, v2 ;

auto iter1 = v1.begin() ;
auto iter1_end = v1.end() ;
auto iter2 = v2.begin() ;
auto iter2_end = v2.end() ;

for( ; iter1 != iter1_end && iter2 != iter2_end ;
    ++iter1, ++iter2 )
{
    DoSomething( *iter1, *iter2 ) ;
}

そこで、range-based forを拡張して、セミコロンで区切ることで、複数のRangeを受け取れるようにする。

// P0026提案

for ( auto && e1 : v1 ; auto && e2 : v2 )
{
    DoSomething( e1, e2 ) ; 
}

レンジの要素の数が同じではない場合、要素数が少ないレンジの終端に達した時点でループが打ち切られる。

P0027R0: Named Types

名前付きの型を作り出す機能の提案。

typedef名は、型に別名をつけることができる。

typedef double Force ; typedef double Mass ; typedef double Accel ; Force calc_force( Mass m, Accel a ) { return m * a ; }

問題は、typedef名はあくまで別名であって、新しい型ではない。そのため、double型を渡すことができる。

void f( Object o )
{
    Mass m = o.get_mass() ;
    Accel a = o.get_accel ;

    // コンパイルエラーにならない
    Force f = calc_force( m, m ) ;
}

これを解決して、論理的に間違っている場合にコンパイルエラーを出すためには、新しい型を作り出す必要がある。

newtype double Force ;
newtype double Mass ;
newtype double Accel ;

提案では、何らかの新しいキーワード(仮にnewtype)を使って新しい型名を宣言する文法を提案している。まだ具体的な文面案がないので、どのようになるかは詳しく書かれていない。

少なくとも、暗黙の型変換は阻害されて欲しいし、テンプレート実引数で異なる特殊化をされてほしい。

提案は先行事例としてAdaを挙げている。また、Adaにはある値の範囲を定める機能: newtype Age is int(0...130)のような案も漏らしている。

P0028R0: Using non-standard attributes

attributeは、アノテーションを記述するのに便利なので、すでによく使われている。たとえば、| Reengineering and Enabling Performance and poweR of Applicationsでは、attributeを使って、GPUやDSPに処理をオフロードするアノテーションを記述できる。

問題は、inとかoutとかの短くてわかりやすい単語を使いたいが、他の実装依存のattributeとかぶるとまずいため、attribute名前空間を用いている。これは記述を煩雑にする。

void f() {
    [[ rpr::kernel, rpr::target(cpu,gpu)]]
    do_task();
}

そこで、同一のattribute内であるattribute名前空間内のattributeトークンをグローバルスコープに持ち込むための機能を提案している。

void f() {
    [[using(rpr), kernel, target(cpu,gpu)]]
    do_task();
}

P0029R0: A Unified Proposal for Composable Hashing

unorderedコンテナーのキーは、ハッシュ値を計算できる必要がある。基本型と標準ライブラリの型はstd::hashでハッシュ値が計算できる。しかし、ユーザーがハッシュ計算可能な型を組み合わせたクラスを作った場合、標準ライブラリはそのような型にハッシュ値を計算させる簡単な方法を提供していない。ユーザーが独自の方法でハッシュ値を計算しなければならない。

ハッシュ値の計算は素人には難しい。そこで、既存のハッシュ計算可能な型のオブジェクトを任意個ぶち込めばハッシュを計算してくれるライブラリhash_valueとhash_combineを提案している。

struct Foo { int i ; std::string str ; bool b ; friend std::hash_code hash_value( std::hash_code h, const Foo & foo ) ; } ; std::hash_code hash_value( std::hash_code h, const Foo & foo ) { return std::hash_combine( std::move(h), foo.i, foo.str, foo.b ) ; }

このようにすれば、Foo型はstd::hashでハッシュ計算ができるようになり、unorderdコンテナーのキーとして使うことができるようになる。

ドワンゴ広告

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

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

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

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

2015-10-13

ゲーム用のPCを買ってゲームを始めた

東京に引越してからというもの、まともなゲームをしていなかった。ゲームをするにはゲーム用の高スペックなPCが必要だが、引越してから色々とやることがあったので、つい他のことを優先してしまった。

しかし、ゲームは重要である。幸い、引越しをして落ち着いた空間を手に入れたのと、Fallout 4が発売されるので、この機会に高スペックなPCを購入した。

以下が筆者のSteamのプロファイルだ。友人申請は気軽にしてよい。

Steam Community :: ezoe

とりあえず遊びたかったゲームを少しづつ消化しているが、本命はFallout 4だ。

C++標準化委員会の文書 2015-09 pre-Kona: P0011R0-P0020R0

P0011R0: Additions to Filesystem supporting Relative Paths

filesystemライブラリに相対パスを作り出す関数の追加。

以下のように使える。

using namespace std::experimental::filesystem ;
path Path  = "/a/d";
path Start = "/a/b/c";

auto RelPath = relative( Path, Start );

assert( RelPath == path("../../d") );
assert( Path == normalize( Start/RelPath ) );

P0012R0: Make exception-specifications be part of the type system, version 4

例外指定を型システムに含める提案。

現在、例外指定は型システムに含まれていない。例外指定された関数へのポインターについて僅かに言及があるだけである。これにより、違法であるべきコードが合法になってしまったり、合法になって欲しいコードが違法になってしまったりする。解決には、例外指定を型システムに含めるしかない。

P0013R0: Logical Operator Type Traits

任意個のtraitsを受け取って論理値を返すand_, or_, not_の追加。それぞれ以下のように宣言される。

template < typename ... B >
struct and_ ;
template < typename ... B >
struct or_ ;
template < typename ... B >
struct not_ ;

以下のように使う。

template < typename T >
void f()
{
    constepxr bool b = and_< std::is_copy_constructible<T>, std::is_copy_assignable<T> >::value ;
}

また、これの変数テンプレート版である、and_v, or_v, not_vも提供される。

[PDF注意] P0014R0: Proposal to add the multiline option to std::regex for its ECMAScript engine

std::regexにregex_constants::multilineを追加する提案。^と$とが、文字列全体の先頭と末尾ではなく、各行の先頭と末尾にマッチするようになる。

// マッチ数をカウントする
unsigned int count_match( std::string const & text, std::regex const & re ) 
{
    std::sregex_iterator iter( text.cbegin(), text.cend(), re ) ;
    std::sregex_iterator end ;

    unsigned int count = 0 ;
    for ( ; iter != end ; ++iter )
    { ++count ; }

    return count ;
} 

int main()
{
    std::regex const re1( R"(^[^]*?$)", std::regex_constants::ECMAScript ) ;

    std::string text = R"(this is
a 
test.)" ;

    std::cout << count_match( text, re1 ) ; // 1


    // multilineオプション
    std::regex const re2( R"(^[^]*?$)", std::regex_constants::ECMAScript | std::regex_constants::multiline ) ;

    count_match( text, re2 ) ; // 3
    
}

P0015R0: A specialization-friendly std::common_type

std::common_typeの実装を変えて、ユーザーが特殊化するときにCV修飾子はリファレンス修飾子の違いによって何種類も明示的特殊化を書かずにすむようにする提案。

P0017R0: Extension to aggregate initialization

アグリゲート初期化を拡張して、基本クラスを持つ型でも初期化できるようにする提案。

C++11のアグリゲート初期化は、基本クラスがある場合には使えない。

struct unique_id { std::uint32_t id ; } ;
struct user : unique_id
{
    std::string name ;
} ;

// エラー
user Adams{ "Douglas Adams"} ;

そのため、基本クラスがある場合には、面倒なコンストラクターを書かなければならない。

user( std::uint32_t id, std::string const & name )
    : unique_id{id}, name(name)
{ }

このようなボイラープレートコードは書きたくない。そこで、アグリゲート初期化を拡張して、基本クラスもメンバーのように初期化できるようにする。

user Adams { {42}, "Douglas Adams" } ;

複数の基本クラスがある場合は、記述された順番に初期化する。

struct unique_id { std::uint32_t id ; } ;
struct Name { std::string name ; } ;

struct user : unique_id, Name { } ;

user u{ {0}, {"null"} } ;

まあ、便利そうだ。

P0018r00 : Lambda Capture of *this by Value

lambda式で*thisを値でキャプチャできるようにする提案。

struct X
{
    int data ;

    std::function<int ()> f()
    {
        return [*] { return data ; }
    }
} ;

int main()
{
    std::function< int () > f ;

    {
        X x ;
        f = x.f() ;
    }// xは破棄された

    f() ; // OK、*thisはコピーキャプチャされている
}

キャプチャーデフォルト*は=とほぼ同じだが、thisポインターではなく、*thisを値でコピーキャプチャーする。

*thisだけをコピーキャプチャする、*thisもシンプルキャプチャーとして書ける。

P0019r00 : Atomic View

非アトミック型のオブジェクトに対してアトミック操作をするviewライブラリの提案。

atomic_viewは、非アトミック型の単一のオブジェクトに対してアトミック操作を提供する。

int x = 0 ;

i = 42 ;

{// iへのこれ以前の操作は全て行われる
    std::atomic_view<int> ai(i) ;
    // atomic<int>風の操作ができる
    // aiを介して操作する限りアトミックになる
}// ai破棄、aiへの操作がiに反映される

実装方法として最も汎用的なものは、mutexのような排他的ロックを使うことだ。もっと効率的な方法としては、まずアトミック型にコピーして、アトミック型のオブジェクトを経由して操作を行い、viewオブジェクトが破棄されるときに元のオブジェクトに結果をコピーするというものだ。

atomic_array_viewは、非アトミック型の配列に対するアトミック操作を効率的に行う意図で用意されている。例えば、排他的ロック実装の場合、ロックを要素ごとではなく配列全体に対して単独で用意できる。

想定用途は巨大な配列に対する高パフォーマンス演算だ。以下のような用途を想定している。

  1. 巨大な非アトミック型の配列を確保する
  2. 並列の競合しない初期化を非アトミック操作で高速に行う
  3. atomic_array_viewを構築する
  4. 並列の競合する書き込みをview経由で行う
  5. viewを破棄
  6. 並列の競合しない読み込みを非アトミック操作で高速に行う

atomic_global_viewは、グローバルにアクセス可能なアトミック型のオブジェクトをアトミックに操作するためのviewだ。インターフェースはatomic_viewと同じ。意図としては、アトミック型へのコピーを行わず、元となる非アトミック型を直接操作するものらしい。

P0020r00 : Floating Point Atomic View

非アトミックな浮動小数点数型に対するアトミック操作を提供するatomic_viewに、整数型と同等のメンバーを追加する提案。

add/sub/fetch_add/fetch_sub/operator +=/operator -=が追加される。

ドワンゴ広告

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

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

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

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

Boost.勉強会 #18 大阪で発表してきた

Boost.勉強会 #18 大阪 - Boost.勉強会 大阪 | Doorkeeper

Boost.勉強会 #18 大阪で発表してきた。発表資料はGitHubに上げている。

EzoeRyou/boost-benkyo-18

発表内容は、2週間前に公開されたpre-Kona mailingの提案から興味深いものを抜粋している。

Boost勉強会が大阪であるので、ドワンゴに金を出してもらって出張という名目で発表してきた。

なんでも午前11時から始まるそうだ。当日に東京から新幹線で大阪まで向かうので、7時頃には家を出なければならない。眠いのを我慢しながら家を出て、新幹線に乗り、大阪に向かった。

そして、大阪駅で30分ほど迷った。大阪梅田のあたりはますます複雑なプロシージャルダンジョン生成アルゴリズムを導入したと見える。

11時をやや遅れながら会場に到着すると、何と誰もいない。何でも、発表者が少ないので13時からに変更になったという。

さて、発表開始だ。

まず最初は、区間演算ライブラリを開発したという発表だった。区間演算ライブラリは多数あるし、Boostにもあるが、皆Partial Orderingでの比較しかサポートしていない。Weak orderingとTotal orderingもサポートしたライブラリを作ったという。しかし利用者がいないという。

発表者に投げられた厳しい意見としては、そもそも何に応用することを目的としたライブラリなのか。既存のライブラリがPrtial orderingしかサポートしていないのには相応の理由があるはずで、用途を考えずに単に純粋に計算だけするライブラリがあっても使われるはずがないとのことであった。

次にでちまるさんの兄のタグ付き共用体の発表のはずであったが、当日の朝にMicrosoftの不自由なPower Pointを購入してスライド資料を作り始めたので、まだ出来上がっていないとのことであった。怠惰はプログラマーの美徳とはいいながら、スライド資料の遅延評価はお勧めできない。

代わりに私が発表した

その次にでちまるさんの兄が発表した

次の発表は、Boostに追加が予定されている新時代のメタプログラミングライブラリ、Boost.Hanaの紹介だった。型計算と値計算を相互に行き来できるライブラリだそうだ。

最後の発表は、Proxygenを使ったWebアプリケーションの発表。なんだかWebの歴史を一通り見ているような内容だった。ブラウザーが高速化のために複数のHTTPコネクションをサーバーにはっていた時代があったことを思い出した。

その後は近所の安い飲み屋で懇親会を行った。Boost勉強会の規模が年々縮小しているという話を聞いた。果たしていつまで続くだろうか。また、大阪は学生の発表が多いという話だが、それは事情が違っていて、職業プログラマーはみんな東京に行ってしまうので、学生しか関西に残っていないのだという話だった。

10時半ごろに確保していたホテルに向かったが、極めて常識はずれなことに旅行会社が喫煙可の部屋を手配したので、極めて煙草臭かった。翌日の始発で家に帰った。

ドワンゴ広告

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

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

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

2015-10-10

スマフォの近くで話をしたらFacebookに関連する広告がでたんだけどマイクで音声拾ってやがるのか?

[Discussion] Facebook listening to conversations through microphone? : jailbreak

Redditで、害虫に悩まされたので、スマフォの近くで大声で害虫を駆除する話をしていたら、何も害虫駆除の検索などはしていないのに、Facebookが害虫駆除の広告を出したという話が注目を集めている。

しかし、Facebookのアプリはマイクの利用権限を要求しない。iOSの脆弱性を利用して権限を回避しているのでもなければ、マイクは使えないはずだ。

Hacker Newsのコメントでは、「その地域のその時期は害虫被害が発生しやすいので広告を入れたのではないか」とか、「友達に害虫のことを話したから、友達が検索したのではないか。友達の興味のあることは、自分も興味があるだろうから、広告が表示されたのではないか」などと推測されている。

十分に発達した科学はなんとやら。

2015-10-07

C++標準化委員会の文書2015-09 pre-Konaのレビュー: P0001R0-P0009R0

今回から、文書番号の規則が変わっている。PxxxxRxというフォーマットになっている。Pxxxxが文書番号で、Rxがリビジョン番号だろう。たしかに、今までどの文章がどの文章の改訂版かわかりにくかったので、いい変更だ。

P0001R0: Remove Deprecated Use of the register Keyword

registerキーワードを廃止する提案。registerキーワードは2011年にdeprecatedになり、将来のために予約されることになった。C++17では廃止する。

廃止するにあたっての懸念は、Cとの互換性だ。例えば、関数のシグネチャがCとC++で変わってしまう。とはいえ、registerキーワードの使用はCでも廃れているし、もっと利用例があるrestrictキーワードでさえ、この15年の間、CとC++との互換性にそれほど大きな問題を引き起こしていないので、大丈夫とのこと。

register機能は廃止されるが、registerキーワードは、将来の利用のために予約される。一般的な英単語のキーワードは極めて貴重である。

registerを予約語から消してユーザーに識別子として解放する案は、会議により否決された。

キーワードといえば、asmも実質廃止しても良さそうな気がする。というのも、C++規格のasmの文法は極めて使いづらいので、現実のコンパイラーは__asmなどの独自のキーワードを使ってインラインアセンブリを提供している。

NP0002R0: Remove Deprecated operator++(bool)

boolに対するoperator ++を廃止する提案。以下のようなコードが違法になる。

bool b = true ;

++b ; // false
++b ; // true

boolに対するoperator ++は、そもそも正式な規格以前の機能で、C++98ですらdeprecated扱いになっている。もう20年以上の猶予期間を与えてやったのだから、いい加減にいいだろうということだ。

なお、後置演算子はまだ利用価値がある。というのも、現在の値を得つつ値を変更できるからだ。

void f( bool b )
{
    g( b++ ) ; // 値を渡しつつ変更
}

この代替機能として、ライブラリにstd::exchangeが導入された。

void f( bool b )
{
    g( std::exchange( b, !b ) ) ;
}

P0003R0: Removing Deprecated Exception Specifications from C++17

動的例外指定を廃止する提案。

まともに利用されなかったので、すでにC++11でdeprecated扱いされている。

throw()だけは残されるが、noexcept(true)と同じ意味になる。

P0005R0: Adopt 'not_fn' from Library Fundamentals 2 for C++17

Library Fundamentals TSにあるnot_fnを標準ライブラリに追加する提案。

auto f = []( bool b ){ return b ; } ;
auto nf = not_fn(f) ;

f( true ) ; // true
nf( true ) ; // false

not_fnは小さいし、not_fnが依存する他のライブラリもないので、not1, not2の代替機能として。

P0006R0: Adopt Type Traits Variable Templates from Library Fundamentals TS for C++17

Library Fundamentalsにある変数テンプレートを使ったtype traitsのラッパーを標準ライブラリに追加する。traits::valueのかわりに、traits_vで値が返。is_same<T, U>::valueと書くかわりに、is_same_v<T, U>と書ける。

変数テンプレートは以下のように使う。

template < typename T, typename U >
constexpr bool is_same_v = std::is_same< T, U>::value ;

P0007R0: Constant View: A proposal for a 'std::as_const' helper function template

constなlvalueリファレンスを返す関すテンプレート、as_constを追加する。

利用例は以下の通り。

struct X {  } ;

void f( X & ) ; 
void f( X const & ) ;

int main()
{
    X x ;

    // 非const版
    f( x ) ; 

    // const版
    f( std::as_const(x) ) ;
}

関数を呼ぶときに、意図的に非constなオブジェクトから、const版のオーバーロードを呼び出したいときに使える。

わざわざconst_cast< const T & >( object )と書くのはだるい。しかもobjectの型Tを明示的に書かなければならない。const_cast< std::add_const< decltype( object ) >::type & >( object )と書けば明示的に型を書く必要はないが、極めてダルい。

実装例

template <class T> add_const_t<T>& as_const(T& t) noexcept
{
    return t ;
}

P0008R0: C++ Executors

スレッド風の実行媒体であるexecutorの提案。asyncをかなり高機能にしたものとも言える。スレッドプールなexecutorなどが提供される。

N4414で提案されていたtype erasure executorは懸念事項があるため見送り。

executorがシャットダウンするタイミングについては、main関数の実行を抜けたら自動的にシャットダウン。明示的にシャットダウンさせる方法については、まだ検討中。その他様々な会議での議論内容が書かれている。

P0009r00 : Polymorphic Multidimensional Array View

連続したストレージを多次元配列に見せかけるラッパー、array_viewが提案されているが、この論文は、array_viewはゼロオーバーヘッドの原則を満たさないし、異なるメモリレイアウトに対するゼロオーバーヘッドabstractionもできない欠陥品だとしている。この論文は、array_viewに対抗したviewライブラリを提案している。extentやstrideをconstexprで提供することによりコンパイラーの最適化の余地を高め、様々なハードウェアが直接サポートするレイアウトに直接マッピングできるようにするなどの設計になっている。とてもシンプルなので、viewというシンプルな名前こそがふさわしいと主張してる。

array_viewでfloat型の三次元配列[5][5][5]を宣言するには以下のようになる。

std::size_t size = 5 * 5 * 5 ;
float buffer[ size ] ;
array_view< float, 3>( size, buffer ) ;

対して、viewでは以下のように宣言する。

std::size_t size = 5 * 5 * 5 ;
float buffer[ size ] ;
view< float[5][5][5]> a( buffer ) ;

要素数がわからない場合は、以下のように設定する。

int x = 5, y = 5, z = 5 ;
float buffer[ x * y * z ] ;
view< float[][][] > a( buffer, x, y, z ) ;

コンパイル時にサイズがわかる箇所だけ書ける。

view< float [][5][] > a( ... ) ;

このような記法を可能にするため、コア言語にも手を入れる。配列の宣言子で、任意の添字の省略を認める。Clangではコードを一行修正するだけで対応可能だそうだ。

すごく大胆な提案だ。使い勝手は確かによい。

ドワンゴ広告

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

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

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

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

C++標準化委員会の文書2015-09 pre-Konaのレビュー: N4545-N4552

ISO/IEC JTC1/SC22/WG21 - Papers 2015

またもやC++標準化委員会の文書集の時期になった。

N4545: PL22.16/WG21 draft agenda: 4-9 May 2015, Lenexa KS/US

kona会議の予定表のドラフト

[PDF注意] N4546: Agenda and Meeting Notice for WG21 Concepts Telecon

コンセプト電話会議の予定表と告知

N4547: Business Plan and Convener's Report

今後の予定。次のC++規格は2017年に発行する予定。

ネットワーキングTSは2015年か2016年までにPDTSドラフトを出して、2016年に発行予定。コンセプトTSはPDTSコメント解決済み、2015年に発行予定。配列拡張TSは作業中だが、破棄されるかも。Concurrency TSはPDTSを出して、2015年に発行予定。

N4558: WG21 2015-07-20 Telecon Minutes

2015年7月20日に行われた電話会議の議事録。

N4549: Programming Languages -- C++ Extensions for Concepts

コンセプトTSの文面だが、古い。R0121R0が最新だ。

N4550: Record of Response: National Body Comments on ISO/IEC PDTS 19217, Technical Specification: C++ Extensions for Concepts

コンセプトTSに対するNBコメントとその対応。日本からは特に誤りを発見できなかったので送っていない。

N4551: National Body Comments, ISO/IEC PDTS 19571, C++ Extensions for Concurrency

Concurrency TSに対するNBコメントの修正。日本からはeditorialな問題の修正が通った。

N4552: Agenda and Meeting Notice for WG21 Telecon Meeting

2015年10月9日に行われた電話会議の告知。

ドワンゴ広告

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

今週末はBoost勉強会大阪#18で発表する予定だ。

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

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

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

Sarah Sharp、Linuxカーネルコミュニティの暴力性に嫌気がさして貢献をやめる

Closing a door | The Geekess

ドアは閉められた

この記事は一年もの間、下書きフォルダーに入れてた。いまこそ投稿すべき時。炎上は怖かったので、この問題について触れるのはなるべく避けてきたのだけれど、部屋の中の象を指摘しないのはもやもやする。そういうわけで、公開する。

つまりこういうこと。私はもうLinuxカーネル開発者じゃなくなった。2014年の5月にUSB 3.0ホストコントローラードライバーのメンテナーの座を明け渡したし、2015年の1月には女性向けFOSS推進計画(FOSS Outreach Program for Women)のLinuxカーネル部門とかその他の役職も降りたし、2014年12月6日には、最後のLinuxカーネル開発のプレゼンをした。2015年8月のシアトルでのLinux Plumbers Conferenceへの協力は断った。Linux財団の技術顧問委員の任期もすぐに切れるし、次回に入るつもりはない。

私はできることなら、もう二度とLinuxカーネルのメーリングリストに対してパッチやバグ報告や提案を投げることはない。受信欄には最近のカーネルの不具合がたまっているが、無視する。今やっているユーザースペースのグラフィックの仕事上、カーネルの不具合のパッチを投げる必要があるかもしれないが、カーネルコミュニティのやかましいやり取りに悩まされることを考えると、まず丸一日は躊躇するだろう。

私はもうLinuxカーネルコミュニティの一員とはならない。

この決断は長いこと考えたあげくのことだ。今の立場から降りることは軽々しく行ったのではない。降りたことに対して、長い間罪悪感を感じていた。でも、技術的には尊敬されこそすれ、個人的に尊敬されないようなコミュニティに貢献することなどできるはずがないとようやくわかったのだ。新参にはパッチを送るよう推奨しておきながら、メンテナーはどんな暴言でも吐くことを許されるような人間と関わり合いたくはない。下ネタとホモフォビックジョーク飛ばして何のお咎めもない連中と共同作業などできるはずがない。行動を律する規則なく、また規則を守らせる権力の存在しないコミュニティのなかでは無力だ。

Linuxカーネルコミュニティの技術力は認めている。この世の中で一流のコード品質を維持するほどに成長したプロジェクトだ。文化や習慣の違うメンテナーが膨れ上がるなかで、技術力に注力するということは、Linuxカーネルメンテナーは作業をすすめるために、往々にして愚直で、礼儀知らずで、暴力的になる。トップのLinuxカーネル開発者達は、他人の行動を正すために、たいてい怒鳴りあう。

こういうコミュニケーション方法は私向きではない。技術的に愚直なのはいいとして、人間は尊重しなければならない。技術的にせよ、社会的にせよ、間違いを犯した時は、個人攻撃せずに正すコミュニティでなければならない。我々は皆人間であり、間違いを犯す。そして正す。誰かにいらだち、やりすぎ、謝り、一緒に解決策を考える。

Linuxカーネルコミュニティのコミュニケーション方法はもっと礼儀正しくあるべきだ。メンテナーが不満を抱えているときにコミュニケーションを行うときに、もっと健全な方法を取るべきだ。Linuxカーネルには挑発や愚直を避けるために、もっとメンテナーが必要だ。

残念ながら、Linuxカーネルコミュニティに私が望むような態度の変化は近い将来に起こりそうもない。多くの古参Linuxカーネル開発者は技術的に性格的にも暴力的であるために現在の地位にいる。たとえ直接対面すればいい人であったとしても、彼らは現在のLinuxカーネルのコミュニケーション方法に変化を望んでいない。

つまり、このLinuxカーネルコミュニティにおいては、他のLinuxカーネル開発者の感情的な需要(ストレスを他人に愚直で失礼で暴力的な方法でぶつけて発散させること)が、私の感情的な需要(人間として尊重されること、罵倒されないこと)より優先されるということだ。このコミュニティでは基本的人権の尊重より既存のメンテナーを優先する強力な政治力が働いている。

この記事はカーネル開発者に向けて書いているわけではない。誰か特定の人間のせいにしているのではない。この記事は、私がもうその一員とならないコミュニティに対する失望だ。コミュニティをより良くするために私が立ち上がるたびに賛同してくれた人たちに申し訳なく思う。というのも、私はLinuxカーネルコミュニティの変化を諦めたからだ。文化の変遷は遅く、難しい作業だ。私はもはや文化の変遷を先導する一員にはなれないということだ。

Linuxカーネルコミュニティがいずれ変わることを願っている。その変化の片鱗には私がいる。ドキュメント、チュートリアル、そして私が始めた女性向けカーネルインターンシップ制度は、私がいなくても成長していくだろう。いずれの日か、環境が良くなれば、私は戻るかもしれない。私にはまだ時間がある。私は待てる。その間、他に私の活躍できる、もっと友好的なオープンソースコミュニティがいくつもあるというものだ。

あるドアが閉まれば、また別のドアが開く。しかし、我々は往々にして閉まってしまったドアのことを残念がり、新たに開かれたドアには目もくれない。

Alecander Graham Bell

ところで、HackerNewsではUSBスタックの不具合を修正するためにカーネルメンテナーとやり取りしたが、そのメンテナーがあまりにもやる気がなかったため諦めた体験談が書き込まれている。サラ・シャープもUSBスタックのメンテナーであった。これを受けて、ひょっとしたらLinuxカーネルの特定の領域のメンテナーとその文化がクソなのではないかという推測がされている。特に、既存のコードの保守が主な作業になると、自然と担当者の考え方まで保守的になるのではないかなどと議論されている。

Sigh. Story time. A long time ago (2006,7,8?) before Sarah took over USB develo... | Hacker News

また、有名なカーネル開発者のMatthew Garrettが、この記事を受けて、LinuxカーネルにBSD風のsecurelevelインターフェースを加えたforkを発表している。

mjg59 | Going my own way

2015-10-03

自作のサポセン応答AIを作ったとされるニューヨーク市の職員は単にロボット声で応答していただけだった

以下のような報道記事が上がっている。

ニューヨーク市のヘルプデスク職員、自作のAIプログラムに仕事をさせて停職処分 - BusinessNewsline

日付は執筆時点で"Posted Yesterday, by Anthony Holt"と書かれている。つい昨日、2015年10月2日の最新のニュースだ。ガイジン風の名前も信憑性が高い。おそらくは翻訳記事に違いない。重要な内容は以下の通りである。

ニューヨーク市がヘルプデスクの電話対応の作業を自作のAIプログラムに代行させていたとして、このヘルプデスクの職員に対して停職20日間の処分を下していたことが判った。

この職員は、Ronald Dillonという人物で、彼は自分の声とそっくりの自動音声応答システムを自作してヘルプデスクにかかってくる様々な質問をそのAIシステムを使って答えさせていた。

しかし、対応に疑問を感じた人が通報を行うことで、AIプログラムを使って電話対応を行わせていたことが発覚し、今回の処分に至った。

彼が自作したプログラムは、電話を通じて完璧にヘルプデスクの対応を行うことができるというもので、普通に電話対応を聞いた範囲では、対応を行っているのが人間ではなくロボットプログラムであるということを認識することはできない程の高度なものとなる。

このことは既に、多くのマスコミで報じられる状況ともなっており、ニューヨーク市が仕事をさぼった職員を停職処分にしたという以前の問題として、彼の作ったAIプログラムの出来があまりにも高度すぎることが大きな関心を集めている。

一部報道によるとこのRonald Dillonという人物は数学科を卒業してMBAを取得した秀才で、ニューヨーク市では元々はシステム開発のプロジェクトマネージャーをしていたが、その後、システム部が外部委託となったことを受けて、ヘルプデスクのサポート係に異動になったとしている。

なるほど、実際スゴイニュースだ。ヤバイ級ハッカーをサポセンのような分不相応にスゴイシツレイな職にあてがったために起こった痛快なニュースのように読める。このハッカーのウカツな上司にはケジメが必要だろう。

記事にはRonald Dillonなる人物の実際の応答音声らしきものがある。さて聞いてみると、呼吸や間投詞が多く、ものすごく高度に洗練された合成マイコ音声を使っていることがわかる。さすがネオニューヨークのハッカーは格が違う。

いやそんなバカな。そんな自動応答システムは、仮に作れたとしても、一人の天才の手によって作れるわけがない。「すでに、多くのマスコミで報じられる状況」で、ニューヨークの出来事であるので、さぞかし英語圏の報道も多いであろうと検索してみたところ、以下のような記事が引っかかった。

City Worker Gets 20-Day Suspension for Using Robot Voice to Answer Phone - Civic Center - DNAinfo.com New York

日付は2014年10月31日、去年のニュースである。これによると、

ニューヨーク市の保健局の職員は、カスタマーサービスの電話にロボット声で対応したことにより、20日間の停職処分を受けた。処分を受けた職員のRonald Dillonは同僚と一般市民に対するコンピューター関係の問題を解決する職についているが、上司の注意にもかかわらず、電話の応答に、意図的にロボット風の声を出して応答したという。

保健局によれば、2013年の2月から4月にかけて、少なくとも5回はロボット声(記事中では、Siri風、droid模倣という表現も使われている)で応答したという。

調査に使われた録音では、Dillonは電話口で、「ゆっくりとした、抑揚のない、過剰に明瞭な発音」で話したという。

Dillonによれば、ロボットを真似たのではなく、単に上司に渡されたマニュアルをゆっくりと読み上げただけだという。

Dillonは速いブルックリンなまりで話すので、うまく聞き取れないことがあるために単語ごとに読み上げたのだという。

Dillonはまた、彼はあまり人から好かれない性格であるため、上司が見せしめのために処罰を加えたのだと主徴している。

取材に答えたDillonは、上司から自分の声の抑揚について注意されたので、なるべく聞き取りやすい声を出すように努力しただけだと答えている。

裁判では、Dillonは上司に反抗するために意図的にロボット声を出したと判断された。

Dillonは1976年から保健局で働いていて、これまでにこのような処分を受けたことはない。

Dillonはかつて保健局のプロジェクトマネージャー(技術的なものであるとは書かれていない)であったが、3年前に本人の意思に反してサポセン業務に配置転換させられたという。サポセン業務はDillonには経験がなく、十分にこなす能力もない。「パワハラである」と主張している。

さて、もうひとつの記事がある。

NYC Health Department worker answers phone in robot voice - NY Daily News

日付は2015年9月29日。去年30日の停職処分を受けたRonald Dillonは、またもやロボット声を模倣したかどで、20日の停職処分にあったと報じているニュースだ。

保健局に寄せられる苦情のほとんどはDillonのロボット声に対するものである

上司によれば、Dillonは自分の技能と教育が現在のサポセン業務には分不相応であるが、配置転換が認められないため、仕事をサボタージュしているのであるという。

Dillonはこれを否定したが、裁判では認められなかった。

自動応答AIを開発したなどという話は英語圏のニュースには一切見当たらない。

2015-10-01

C++11/14 コア言語が出版された

「C++11/14 コア言語」が出版された。

C++11/14 コア言語

内容は、すでに去年公開しているものと同じだ。

EzoeRyou/cpp-book

EzoeRyou/cpp14-appendix

この本が出版に至るまでに実に様々な出来事があったのだが、今となっては語っても仕方がないことだ。

ドワンゴ広告

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

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

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