本の虫

著者:江添亮
ブログ: http://cpplover.blogspot.jp/
メール: boostcpp@gmail.com
Twitter: https://twitter.com/EzoeRyou
GitHub: https://github.com/EzoeRyou

アマゾンの江添のほしい物リストを著者に送るとブログ記事のネタになる

筆者にブログのネタになる品物を直接送りたい場合、住所をメールで質問してください。

2014-11-post-Urbanaのレビュー: N4310-N4319

N4310: Technical Specification for C++ Extensions for Parallelism, Working Draft

Parallelism TSのドラフト

[PDf] N4311: Parallelism TS Editor's Report

Parallelism TSの編集者の報告書

[PDF] N4312: Programming Languages -- Technical Specification for C++ Extensions for Parallelism

N4311と内容は同じ。

N4313: Improvements to the Concurrency Technical Specification, revision 1

<future>にwhen_all, when_any_result, when_any, make_ready_future, make_exceptional_futureを追加する提案。

N4314: Data-Invariant Functions (revision 2)

入力の値におって、処理時間が異なるなどの外部から計測可能な挙動の違いが存在する場合、外部からその違いを計測することによって、秘密の情報が漏れてしまうことがある。暗号処理の実装において、サイドチャネル攻撃として知られている問題だ。

最近のOpenSSLのパッチは、そのような問題に対処するために入力によって処理速度が変化しないようにプラットフォーム依存の方法で対処している。

そのような仕組みは標準に存在するべきである。この論文では、入力の値によって外部から計測可能な挙動の変化が生じないような基本的な演算を提供するライブラリ、std::constant_time::value<T>を提供している。

// 入力の値によって処理時間やメモリアクセスパターンに差がでないことが保証されている
auto equal( std::constant_time::value<int> a, std::constant_time::value<int> b )
{
    return a == b ;
}

N4315: make_array, revision 3

std::arrayを作るstd::make_arrayの提案。

// 面倒
std::array<int, 5> a1 = { 1, 2, 3, 4, 5 } ;
// 簡単
auto a2 = std::make_array( 1, 2, 3, 4, 5 ) ;

// 面倒
atd::array<char, 4> a3 = { 'a', 'b', 'c', '\0' } ;
// 簡単
auto a4 = std::to_array("abc") ;

// std::array< char const *, 1 >
auto a5 = std::make_array("abc") ;

これは自分で実装してみるとVariadic Templatesの練習になって面白い。

リファレンス実装が公開されている。

N4316: std::rand replacement, revision 2

std::randの代替品、std::randintの提案

前回の変更点は、seed関数がseed_initからreseedに解明されたことだ。

[PDF] N4317: New Safer Functions to Advance Iterators

イテレーターを進めるadvanceとnextとprevに終端をチェックする安全版を追加する提案

例えば、イテレーターを三つ進めるごとに処理をしたいとする。以下のように書くと問題がある。


for ( auto i = begin(con), e = end(con) ; i != e ; std::advance( i, 3 ) ) 
    process( *i ) ;

このループは、イテレーターを三回進めるごとに終端のチェックを行っている。イテレーターの指す要素の数によっては、終端を飛び越してしまう可能性がある。

終端をチェックしつつイテレーターを進めるadvance, next, prevを追加しようという提案。この提案を使えば、以下のように書ける。


for ( auto i = begin(con), e = end(con) ; i!= e ; std::advance( i, e, 3 ) )
    process( *i ) ;

advance, next, prevに、終端のイテレーターを取るオーバーロードが追加される。

[PDF] N4318: Proposal to add an absolute difference function to the C++ Standard Library

絶対値の差を計算するabs_diff(a, b)の提案。

operator <とoperator -をサポートする型のオブジェクトの絶対値の差を計算してくれる。

int main()
{
    // 2
    std::cout << abs_diff( 3, 5 ) << '\n' ;
}

従来のabsでこれをやろうとすると、abs(a - b)のようになる。しかし、もし型が符号なし整数型で、bの方が大きい場合、悲惨なことになる。


int main()
{
    std::cout << abs( 3 - 5 ) << '\0' ;
}

結果は好ましい物にならないだろう。

[PDf] N4319: Contracts for C++: What are the Choices

会議の結果、contract programming(契約プログラミング)をコア言語で直接サポートすべきという意見に固まったが、contractに対するそれぞれの意見や経験がバラバラである。Microsoftの既存の経験から、contractの土台を解説している。

なぜcontractが必要なのか。

contract systemに求めるもの

  1. あるコードに対する要求(required)と保証(ensured)を直接表現できること。たとえば、関数を呼び出す前と呼び出した後の条件や、通常時と異常時の挙動など。
  2. アノテーションによるオーバーヘッドを最小化する。contractは既存の機能と強調して働き、将来の発展を妨げるものであってはならない。
  3. 静的と動的な解析ツールや、コンパイラーの最適化の役に立つ
  4. あまりに冗長な文法ではないこと

論文著者は、contractが受け入れられるには、軽量な文法であることが必要であるとしている。

論文は、既存のマイクロソフト製品におけるContract機能を紹介している。

.NETのCodeContracts

public void TurnReactorOn()
{
    Contract.Requires(this.state == State.Off);
    Contract.Ensures(this.state == State.On);
    ...
}

このコードは、関数が呼び出される前はreactorが動いていないことを要求し、関数が呼び出された後はreactorが動いていることを保証するものである。これはライブラリで実装されている。実行時のチェックと、静的解析ツールによるチェックが行われる。

SAL

SALはプリプロセッサーマクロを多用した契約の記述だ。

void * memcpy(
_Out_writes_bytes_all_(count) void *dest,
_In_reads_bytes_(count) const void *src,
size_t count
);

この宣言は、destに書き込まれるバイト数とsrcから読み込まれるバイト数のアノテーションだ。MSはSALにより数多くのバグを発見して修正できているとしている。

System C#

System C#はC#の拡張で、言語機能としてcontractをサポートしている。

public string Format(int x)
requires x >= 0
ensures return != null
{
...
}

このコードは、関数が呼び出される前に、xが0ではないことを要求し、関数の戻り値がnullではないことを保証している。

ドワンゴ広告

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

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

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

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