2017-02-15

C++標準化委員会の文書: 2017-02のまとめ

2017-02 Pre-Kona mailingsが公開されている。

#MAILING2017-0: ISO/IEC JTC1/SC22/WG21 - Papers 2016

参考書の執筆に注力したいため、この記事では改訂版の提案のうち興味深い文書を取り上げる。

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

モジュールのドラフト

[PDF] N4640: Working Draft, Standard for Programming Language C++

現在のドラフト。変更点はeditorial上のものにとどまる。valarrayの文面が最新の用語を使って書き直された。

[PDF] P0045R1:Qualified std::function signatures

constなstd::functionにconstではない関数オブジェクトを代入するとconstなオブジェクトが変更できてしまう問題がある。

struct delay_buffer {
int saved = 42;
int operator () ( int i ) { return std::exchange( saved, i ); }
};
// Small object optimization — no heap allocation.
const std::function< int( int ) > f = delay_buffer{};
assert ( f( 1 ) == 42 );
assert ( f( 5 ) == 1 );

この問題への対処として、std::functionのテンプレート実引数にconst修飾を書けるようになる。既存のconstなstd::functionは[[deprecated]]を利用してdeprecated扱いであることを明示した上でconst_castを使う

std::function< void() > const f = []() mutable {} ;
f() ; // [[deprecated]]警告付きで動作する

// コンパイルエラー
std::function< void () const > const g = []() mutable {} ;

これは便利だ。

[PDF] P0052R3: Generic Scope Guard and RAII Wrapper for the Standard Library

汎用RAIIラッパーライブラリ、だいぶ仕様が固まってきたので、これ以上大きな変更はなさそうだ。

[PDF] P0059R3: A proposal to add a ring span to the standard library

固定長リングバッファーを実装するring_spanの提案。ring_spanはストレージを管理せず、コンストラクターでcontiguous iteratorで渡されたストレージを使う。

この提案では、ring_spanからイテレーターを得るbegin/endが削除された。ring_spanはストレージを所有しないため、イテレーターを提供するのは好ましくないとのことだ。

[PDF] P0082R2: For Loop Exit Strategies (Revision 3)

繰り返し文を条件式がfalseになって抜けたのか、break文で抜けたのかによって、繰り返し文を抜けた後で条件分岐したいことがある。しかし、C++ではそれを直接表現する方法がないので、極めて冗長かつ非効率的な方法で書かなければならない。

bool did_break = false ;

for ( ... )
{
    if ( ... )
    {
        did_break = true ;
        break ;
    }
}

if ( did_break )
    ... ;
else
    ... ;

この提案はC++に繰り返し文のあとにbreakで抜けたかどうかで条件分岐する文法を追加するものだ。この改訂版では、既存のキーワードを使い回すのではなく、新しいキーワードを追加する設計に改められた。


for ( int i = 0  ; is_completed(i) ; ++i )
{
    if ( is_error() )
        break ;
}
on_complete
    do_normal_things() ;
on_break 
    do_abnormal_things() ;

キーワードはon_complete/on_breakだ。

だいぶわかりやすくなった。

P0091R4: Template argument deduction for class templates (Rev. 7)

deduction guideをdelete定義できるようにする提案。まあ、必要になる場合もあるかもしれない。

P0103R1: Overflow-Detecting and Double-Wide Arithmetic Operations

オーバーフローが検出できる整数の四則演算と左シフト演算のライブラリの提案。オーバーフローの有無がbool型の戻り値で、演算結果が実引数に渡したポインター経由で得られる関数と、ひとつの型で返す関数がある


template <typename T> bool overflow_add( T* result, T a, T b );

1つの型で返す関数の方は、split_lowerとsplit_upperで上位下位に分けることができる。

P0104R1: Multi-Word Integer Operations and Types

固定長整数ライブラリの提案

template<int words> multi_int;
template<int words> multi_uint;

演算子がオーバーロードされていて普通に組み込みの整数型のように使える。問題は、現在の文面では、1ワードが何バイトなのか実装依存だということだ。

P0105R1: Rounding and Overflow in C++

浮動小数点数の丸め方とオーバーフローの挙動を指定して演算できるライブラリの提案。

P0237R5: Wording for fundamental bit manipulation utilities

整数型をビットのコンテナーとみなしてビットへのイテレーターなどのアクセス方法を提供するアダプターライブラリの提供。おそらく規格に入る。

[PDF] P0267R3: A Proposal to Add 2D Graphics Rendering and Display to C++,

2Dグラフィックライブラリのドラフト。よくもここまでまとめたものだ。文字列描画機能はないようだ。

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

shared libraryやWindowsのDLLのように、動的に関数やクラスの実装をプログラムにロードして使えるライブラリの提案。果たして標準化できるのだろうか。

P0316R0: allocate_unique and allocator_delete

指定したアロケーターでストレージを確保してunique_ptrを構築するライブラリallocate_uniqueの提案。すでにshared_ptrに対するallocate_sharedはあるので、その補完。

[PDF] P0352R1: Smart References through Delegation (2nd revision)

operator .ではなく派生を使ってスマートリファレンスを実装できる機能の提案。operator .よりよほどマシな文法と意味だ。こちらが採用されるべきだ。

P0355R2: Extending <chrono> to Calendars and Time Zones

<chrono>を日付に対応させる提案。これでようやくCライブラリを使わずにC++で型安全に日付が扱えるようになる。



int main()
{
    using namespace std::chrono_literals;
    auto date = 2016y/may/29;
    cout << date << "\n";
    // 2016-05-29
}

便利だ。

[PDF] P0447R1: Introduction of std::colony to the standard library

flat_mapと同じくらい注目している新しいコンテナーの提案、colony。

colonyはvectorのような連続したストレージ上に構築される要素に順番の概念があるシーケンスコンテナーだが、中間要素への削除が定数時間ですむ。

どのように実装しているかというと、要素の数だけのビットマップを持っていて、それぞれの要素が有効かどうかの情報をビットマップで保持している。これにより、要素をずらす処理が必要なくなる。そして、中間への挿入も無効な要素がたまたまあれば定数時間で終わる。

これはほしい。

P0479R1: Attributes for Likely and Unlikely Statements

分岐先が実行されると期待できる場合と期待できない場合にその情報をコード中に記述できる属性、[[likely]]と[[unlikely]]の提案。


if ( is_unexpected_error() ) [[unlikely]]
{
    // まず発生しないエラーの処理
}

while( is_program_exit() )
[[likely]]{
// 終了することがほとんどないプログラムの処理
}

深いパイプラインを持つ近代的なプロセッサーでは、分岐予測を外した時のペナルティは大きい。もし、プログラム中のある分岐先がほとんど確実に実行される、あるいは実行されないことがコンパイル時にわかっている場合、プロセッサーによっては分岐予測にヒントを与える命令を使うことによって分岐命令のパフォーマンスを上げることができる。そのような情報をソースコードに付加するための属性。

if, while, do while, for, range-based forに記述できる。

既存の提案の改訂版を片付けた。あとは新しい提案のうち興味のあるものだけをさっと解説して参考書の執筆に戻りたい。

ドワンゴ広告

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

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

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

1 comment:

Anonymous said...

ひーほー。新鮮な規格情報だ~。
リングバッファのイテレータなくなったそうですが、頭から尻尾まで舐めるときはvectorのインデックスで舐める感じになるのでしょうか?アルゴリズムにかけられなくなるのはちょっとなぁ。
繰り返しの脱出理由はなんか文脈が脈絡ないように感じます。そんな自分は貧相なのでしょうか。
2Dグラフィックが現実になるのですか?かなり楽しみデス。フォント描画って特許絡んでくるんでしょうか??
動的なライブラリロードってライブラリのフォーマットの規定までやるんですよね?やらなかったらなかなか無理ゲーのような気がします。
chronoの拡張は単純に歓迎です。

参考書頑張ってください!