2016-10-31

C++標準化委員会の文書: P0165R0-P0293R0

P0165R3: C++ Standard Library Issues to be moved in Issaquah

Issaquah会議で議論されるマイナーな問題集。

[PDF] P0187R1: Proposal/Wording for Bit-field Default Member Initializer Syntax

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

前回の提案では以下のような文法が提案されていたが、

struct X
{
    int data : 5 = 1 ;
} ;

この文法は曖昧だとして、以下のような文法になった。

struct X
{
    int data : 5 : = 1 ;
    int another_data : 5 : {2} ;
} ;

P0194R2: P0194R2 — Static reflection

様々な型情報、ソースコード情報を取得する静的リフレクション機能の文面。テンプレートメタプログラミングを土台としている極めて使いづらい設計となっている。

P0195R1: Modernizing using-declarations

using宣言をパラメーターパックに対応させる提案。

template < typename ... Funcs >
struct overload
{
    using Funcs::operator () ... ;
} ;

overloadのようなライブラリを再帰を使わずに簡単に実装できるようになる。

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

nullableな型のためにnone_t型と、ファクトリー関数none<T>()を追加する提案。ポインターやoptionalなど様々なnullableな型に使える。

[PDF] P0201R1: An indirect value-type for C++

ディープコピーを行う版unique_ptr<T>のような型、indirect<T>の提案。前回の提案では、cloned_ptr<T>と呼ばれていた。


indirect<int> i{ new int(42) } ;
// ディープコピーされる
// 新しいint型のオブジェクトが確保されて値42がコピーされる
auto j = i ; 

// 42
std::cout << *j << '\n' ;

// i, jのデストラクターで所有するint型のオブジェクトがそれぞれ破棄される

unique_ptrはポインターを所有し、コピーを禁止し、デストラクターで破棄する。。shared_ptrはポインターを所有し、コピーはリファレンスカウントにより所有権を共有し、デストラクターでリファレンスカウントを減じて、どこからも参照されていなければ破棄する。indirectはポインターを所有し、コピー時にはディープコピーし、デストラクターでは破棄する。

コピーと破棄には、コピーアーとデリーターによって独自の挙動を設定できる。

int * ptr = static_cast<int *>( std::malloc( sizeof(int) ) ) ;
*ptr = 42 ;
indirect<int> i( ptr,
[]( auto ptr ){
    int * copy = static_cast<int * >( std::malloc( sizeof(int)) ) ;
    *copy = *ptr ;
    return copy },
[]( auto ptr )
{
    std::free( ptr ) ;
} ) ;

// mallocでメモリが確保される
auto j = i ;

// freeでメモリが破棄される

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

SIMDやGPGPUなどの並列処理を行うためのベクトル型の提案。

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

ハザードポインターライブラリー、haz_ptrの提案

P0237R3: Wording for fundamental bit manipulation utilities

符号なし整数型に対して、ビット単位のイテレーターを提供するライブラリ。イテレーターを提供することにより、汎用的なアルゴリズムにビット列処理のために渡すことができる。

[PDF] P0249R2: Input Devices For 2D Graphics

2Dグラフィックライブラリのために、GUIプログラミングで一般的なイベント駆動を実現するためにメッセージ処理を行うためのライブラリの提案。

[PDF] P0252R2: Operator Dot Wording

複雑怪奇で理解不可能なoperator .のオーバーロードを可能にする文面案。

このような極めてわかりにくい機能が提案されているのは、おそらくこれがBjarne Stroustrupのお気に入り案件だからだろう。最近のBjarne StroustrupのC++の判断能力は、最近の書籍から判断すると、極めて疑問である。Bjarne StroustrupはC++から引退するべきではないだろうか。

P0261R1: C++ Distributed Counters

高頻度のインクリメントを行うが読み込みはまれなアトミックなカウンターライブラリの提案。

アトミック操作では、インクリメントは読み込みよりコストがかかる。多くのプログラムではカウンターを用いるが、めったに読み込まないカウンターのためにアトミックなインクリメント操作を行うのはスケールしない。そこで、読み込みのコストを犠牲にインクリメントを高速化した分散カウンターが標準ライブラリにほしい。

P0262R1: A Class for Status and Optional Value

値と情報を保有できる、status_valueライブラリの提案。

現在提案されているexpectedは、値か情報のどちらかを保有するライブラリだ。expectedは値と情報の両方を保有したい時には使えない。つまり、

  • 値を保有する。情報は保有しない
  • 値を保有しない。情報を保有する
  • 値を保有する。情報を保有する
  • 値を保有しない。情報を保有しない

というどの状態にもでき、かつoptionalやexpectedのように値がない場合の簡単に書けるようなライブラリを提案している。

こういう目的に特化したライブラリを乱立させるより、C++のコア言語にnullableな値も含む多値を扱える仕組みを入れたほうがいいのではないか。

[PDF] P0279R1: Read-Copy Update (RCU) for C++

RCUライブラリの提案。

P0290R1: P0290R1: apply() for synchronized_value

synchronized_value<T>はT型とmutexを保持するクラスだ。この文書で提案されているapplyは、synchronized_valueをlockして値にアクセスしunlockするための関数だ。

void f( synchronized_value<int> & s )
{
    apply( []( auto value ) { ++x ; }, s ) ;
}

applyは関数オブジェクトと、Variadic Templatesで任意個のsynchronized_valueを受け取る。デッドロックを起こさない方法ですべてロックして、値を関数オブジェクトに渡し、アンロックする。

便利だ。

[PDF] P0293R0: Template deduction for nested classes

クラステンプレート内にネストしたクラステンプレートの実引数推定ができるようにする提案。

趣旨はわかるのだが、すでにC++規格でも標準ライブラリのコンテナーのイテレーターはコンテナークラスの外で定義されるように規定されているので、このような提案が必要になるコードはそもそも扱いづらいので避けるべきではないか。

ドワンゴ広告

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

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

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

2016-10-25

C++標準化委員会の文書: P0009R3-P0099R1

P0009R3: P0009r3 : Polymorphic Multidimensional Array Reference

連続したストレージを多次元配列に見せかけるラッパーライブラリの提案。

柔軟に対応できるようにした結果、すごく使いづらいように思える。

P0019R3: P0019r3 : Atomic View

非アトミックオブジェクトに対してアトミック操作ができるatomic_viewの追加。


// 従来のコード
int data = 0 ;

atomic_view atomic_data( data ) ;

++atomic_data ;

従来のコードをatomic<T>に置き換えるのが現実的ではない場合に使える。

P0020R3: P0020r3 : Floating Point Atomic

atomicライブラリを浮動小数点数に対応させる提案。

P0022R2: Proxy Iterators for the Ranges Extensions

vector<bool>は1ビット単位で要素を格納している。イテレーターは実リファレンスではなくプロクシークラスを返す。イテレーターは実リファレンスを返すことを要件付けられているので、vector<bool>のイテレーターは真のイテレーターではなく、したがってvector<bool>も真のコンテナーではない。

実リファレンスではなくプロクシークラスを使う際の問題は、スワップ操作にあるので、iter_swapをカスタマイゼーションポイントに変えてしまえば解決できる。また、ムーブのためのカスタマイゼーションポイントとして、iter_moveを追加する。

P0037R3: Fixed-Point Real Numbers

固定少数点数、fixed_pointの提案


#include <fixed_point>

int main()
{
    fixed_point< std::uint64_t, 10 > f( 1 ), sum( 0 ) ;
    // tick = 0.0001
    auto tick = f / 10000 ; 

    // 0.0001を1万回足す
    for ( unsigned i = 0  ; i != 10000 ; ++i )
        sum += tick ;

    // 結果は1
    std::cout << static_cast<unsigned>( sum ) << '\n' ;
}

fixed_point< Rep, Exponent >という形で、Repは内部で使用する整数型、Exponentは小数点以下の2進数桁を指定する。

P0040R2: Extending memory management tools

未初期化の生のストレージ上にオブジェクトを構築したりオブジェクトを破棄するための関数テンプレートの追加。トリビアルなデストラクターであればデストラクターを呼ぶ処理をしないなどの最適化が行われる。

[PDF] P0051R2: C++ generic overload function

関数オブジェクトを登録して、登録した関数オブジェクトの間でオーバーロード解決をしてくれるoverloadライブラリの提案。


auto f = overload(
[]( int i ) { },
[]( double d ) { },
[]( std::string s ) { }
) ;

f( 0 ) ;
f( 0.0 ) ;

using std::literals ;

f( "hello"s ) ;

実装はとても簡単。

[PDF] P0057R6: Wording for Coroutines

コルーチンの文面案

キーワードがco_return, co_yeild, co_awaitなのが残念だ。

[PDF] P0059R2: Add rings to the Standard Library

ringバッファーライブラリの提案。前回と違い、ring_spanという名前になった。ring_spanは連続したストレージを受け取り、その上にリングバッファー構造を構築するラッパーライブラリだ。

[PDF] P0098R1:Towards Implementation and Use of memory order consume

タイトル通り、memory_order_consumeの実装と応用の話。もともとは、Linus TorvaldsがC/C++のatomicの仕様にケチをつけたところから始まる。Linuxカーネルでも使えるような実用的なアトミック操作を規格化するために、Linuxカーネルのメモリモデルやアトミック操作の応用を学ぶ文書が多数出た。

[PDF] P0099R1:A low-level API for stackful context switching

レジスターやスタックなどの実行環境ごと保存、リストアするスタックフルコンテキストスイッチを実現するための低レベルなライブラリの提案。

ドワンゴ広告

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

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

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

2016-10-24

C++標準化委員会の文書: N4607-N4617

[PDF] N4607: Toronto Meeting Information

2017年7月の10日から15日にかけてトロントで行われる会議の会場案内。

N4608: PL22.16/WG21 draft agenda: 7-12 Nov 2016, Issaquah, WA, US

N4609: ISO/IEC JTC1/SC22/WG21 N4609

SC22/WG21の議長の事務的な報告書。

2017年11月の7日から12日にかけてIssaquahで行われる会議の日程。

N4609: ISO/IEC JTC1/SC22/WG21 N4609

[PDF] N4610: Working Draft, Extensions to C++ for Modules

モジュールのドラフト。C++17にモジュールは入らないので、現段階ではここまで議論したぐらいの目安にしかならない。

[PDF] N4611: Editor's Report for the Modules TS

モジュールのドラフトの編集者の報告書。

[PDF] N4612: Working Draft, C++ extensions for Networking

Boost.asioを元にしたネットワークライブラリのドラフト。

N4613: Networking TS - Editors Report

ネットワークライブラリのドラフトの編集者の報告書。

[PDF] N4614: WG21 telecon meeting: Pre-Issaquah

Issaquah会議前の電話会議の議事録。

ドワンゴ広告

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

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

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

2016-10-11

C++17のクラスのテンプレート実引数推定

テンプレートは以下のように定義する。

template < typename T >
class C
{
    C ( T t ) { }
} ;

template < typename T >
void f( T t ) { }

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

int main()
{
    C<int> c(42) ;
    f<int>(42) ;
}

しかし、C++プログラマーの大半は、関数テンプレートfをこのように使うことはない。大抵は、f(42)のように使う。このように、テンプレート名を書いた場合、C++コンパイラーはテンプレートの実引数推定と呼ばれる仕組みを使ってテンプレート実引数を推定する。

その詳しい仕組みは難解だが、考え方としてはこうだ。42の型はintである。すると、tの型はintである。tの型はTとされているので、Tはintである。Tはテンプレート仮引数である。するとテンプレート仮引数Tに対する実引数はintである。

テンプレートの実引数推定は、残念ながらC++14ではクラステンプレートには存在しない。しかし、上の例をみるように、クラステンプレートにもコンストラクターがあるのだから、適用できるはずだ。

C++17ではまさにクラステンプレートに実引数推定ができるようになった。以下のように書ける。

C c1(42) ;
C c2 = 42 ;

C++17では、実引数とクラステンプレートCのコンストラクターの仮引数から、クラステンプレートのテンプレート実引数を推定できるようになる。

しかし、C c(42)という形はもっとも簡単なものだ。現実には、以下のような場合もある。

template < typename T >
class C
{
    template < typename Iterator >
    C ( Iterator begin, Iterator end ) ;
} ;

int main()
{
    int a[] = { 1,2,3,4,5 } ;
    // エラー、IteratorからTは推定できない
    C c( std::begin(a), std::end(a) ) ;
}

この場合、IteratorからTは推定できないのでエラーとなる。

この問題を解決するために、C++17では、推定ガイド(deduction guide)という文法が追加される。以下のように書けば、IteratorからTが推定できる。


template < typename T >
class C
{
    template < typename Iterator >
    C ( Iterator begin, Iterator end ) ;
} ;

template < typename Iterator >
C( Iterator begin, Iterator end )
-> C< std::iterator_traits<Iterator>::value_type >

int main()
{
    int a[] = { 1,2,3,4,5 } ;
    C c( std::begin(a), std::end(a) ) ;
}

文法は以下の通り。

テンプレート名 (引数リスト) -> 実引数付きのテンプレート名

2016-10-09

高専プロコンの問題がクソすぎるのでプログラミングを放り出して人力に走るのは最適解であり協賛企業はプログラミングを軽視する企業として唾棄されるべき

第27回高等専門学校プログラミングコンテストが不評を買っている。プログラミングコンテストと名前が付いているのにもかかわらず、本選の上位入賞者は、人力で問題を説いたという。特にコンピューターを持ち込んですらいないチームまでいたという噂まで流れている始末。

なぜそんな残念な結果になるのか、高専生のアルゴリズム力が低いからこうなったのだろうか。この謎を改名すべく、筆者は課題を確認した。

http://www.procon.gr.jp/uploads/procon27/1_Apply27.pdf

課題を要約すると、以下の通りだ。

問題

「一枚の木の板(中密度繊維板)を切り出して、50個以下のピース(凹多面体を含む多角形)に分割する。このピースを枠内で組み合わせて板にせよ。正しい位置のピースの数が得点となる」

制限時間は10分から20分。

その他:コンピューター類を持ち込んでよい。ただし競技ブースに電源はない。外部との通信は認めない。

まるでプログラミングするなと言っているような課題だ。要するに、問題は多角形のパズルを解くものであるが、それは問題の最も簡単な部分である。

ピースは物理的に与えられるので、プログラミングで処理するためには、これを何らかの方法でデータとして表現しなければならない。ピースが十分に薄ければスキャナーが使えるかもしれないが、会場に電源はない。したがってスキャナーのような大電力の装置を稼働させるには、大容量バッテリーか発電機を持ち込む必要がある。

なるべく電力を消費しない方法としては、無地単色の布などを背景に、距離を固定したカメラでピースを一つづつ撮影する必要がある。しかし、制限時間は最大でも20分、ピースは最大50個。撮影装置を一台用意した場合、何のトラブルも起こらずに撮影しても10分から20分の制限時間を超過してしまうだろう。

すると、ピースをすべて並べて一度に撮影して、複雑な画像処理をする必要があるが、カメラの角度がピースに対して正面ではない、レンズの歪み、ピースの加工精度など、様々な要因がピースをデータで表現して処理する際の面倒事となる。

外部との通信が禁じられているので、たとえば画像処理に外部のクラウドサーバーのインスタンスを立ち上げるといったこともできない。

それ以外でも、極めて短い制限時間はやはり問題だ。機器のわずかなトラブルにより、10分、20分程度の時間は容易に失われる。

さて、ここに人間という計算機がある。人間は高精度なカメラ、マイク、スピーカー、多関節脚、マニピュレーターを取り付けられた計算機である。人間は完全に自律移動できる。人間は極めて正確なピースの移動操作ができる。人間のパターン認識能力は極めて高く、完全な乱数列に対して存在しないパターンを見出してしまうほどである。この人間を訓練すれば、パズルを高速に解くことができる。人間はコンデンサの破裂、接触不良、宇宙線によるソフトメモリエラーを起こしたりしない。人間のバッテリー容量はとても高く、外部から燃料を一切供給せずとも長時間稼働できる。

したがって、この問題を解くのに人間を使うのは当然の最適解である。ちなみに、同点の場合、勝敗はサイコロを振って決定される。実際に優勝者はサイコロを振って決定されたそうなので、この戦略は適切であったことが実証されている。

明らかに、この問題と制約(電源なし、制限時間10分、外部通信禁止)はプログラミングコンテストにふさわしくない。この内容でプログラミングをさせたいのであれば、競技ではなく、課題公開から半年から1年ほど問題を解けるシステムを開発させたうえで皆で集まって成果報告会を開くべきである。競技には競技として適切な課題がある。この課題は競技に向かない。

高専プロコンの上位入賞者が人力解答者で占められたのは今年が初めてではない。高専プロコンの課題作成者は競技プログラミングを理解していないとしか言いようがない。この課題は、少し考えただけでも、純粋なプログラミング以外の部分が困難である。課題作成者は自分で課題を解いてみたのだろうか。

そして、この高専プロコンを協賛した企業は覚えておくべきだ。これらの企業は、プログラミングコンテストと銘打ちながら純粋なプログラミング力を競う競技のための課題を作成できず、至極自然で適切な戦略として人力解答者が上位を占めるという失態をしでかしたイベントの恥ずべき協賛者である。これらの協賛企業のプログラミングの認識と熱意と尊敬は、こんなイベントを協賛したレベルである。

全国高等専門学校プログラミングコンテスト - 協賛企業 - 第27回大会

協賛企業

プログラミングコンテストは情報関連企業のみなさまの多大なご協力により運営されています。

これらの企業はプログラミングコンテストの目的や高専教育に対して理解を示して下さっています。皆さんも就職対象として検討されてはいかがでしょうか。

上に引用した内容によれば、これらの協賛企業は、プログラミングコンテストに不向きで人間が最適解である見当違いの課題を設定するこのような謎のイベントの目的に理解を示しているようだ。イベントの実際の内容から考えるに、これらの協賛企業はプログラミングに理解は示しておらず、人間が頑張って単調作業をすることが最適解となることに理解を示しているのだろう。プログラマーの地位と尊厳を重要視する人間はこの事実を踏まえて、就職対象として検討するべきである。

なお、信じられないことに、高専プロコンのWebサイトはこの2016年にもかかわらずTABLEレイアウトを使っていた。繰り返す。TABLEレイアウトを使っていた。お後がよろしくなさすぎる。