C++17ぐらいから,if-initstatementという文法が追加されている.最近の教科書では紹介されないので代わりに私が紹介.
拡張for文
for(auto v: vector){
// do something concern about v
}
この文法は非常にメジャーである.コンテナ型であるところのvectorの要素を一つずつコピーしてきて,その要素をブロック内で執り成すよ,という文法である.
forwarding reference+拡張for文
for(auto& v: vector){
// do something concern about v
}
C上がりたての人たちはあまり使用していないが,C++にはlvalue reference, rvalue referenceという概念がある. lvalue rvalueについて細かく解説はしないが,名前がついているものがlvalue, 名前がついていないもので使用されている部分以外では即時破棄されてしまうようなものをrvalueと呼ぶ,とでも誤魔化しておく.
auto&& x
という文法はforwarding referenceeという文法で,lvalueかrvalueを取り出してきて,その値を参照するためにxを用意する,という文法である.C#に慣れている人であれば関数越しではないoutやrefのようなものと理解してもらえればよい.
この文法を利用することで,vector->vへコピーせずに参照だけ用意するので,vectorの中身がリテラルではないような,例えば2重vectorであるかのような時にオーバーヘッドを少なく取り出すことができる.
if init-statement
本題.
if (const auto err = cudaHostRegister(p, s, cudaHostAllocMapped);
err != cudaSuccess)
{
printf("error code: %d\n\t%s\n", err, cudaGetErrorString(err));
}
C++っぽいことがしたかったので,試しにcudaの例を持ってきた.
cuda APIでは,ほとんどの関数をたたいた時に返り値にそのエラーコードを吐き出す.
このとき,エラーコードはcudaError型の値として取り出されるのである.
Try-Catchなどでも利用するこのようなエラー変数はエラー処理が終わったら基本的には使わない.ifの外ではスコープが切れてほしいとさえ思う.そのような方のためにif init-statementという構文が存在する.if文の中でセミコロン付きで変数を宣言し,それをif文の中で使用できる.if文のブロックを抜けるとスコープが切れる.for文のinitとスコープは同じ挙動を示す.
これだけだと,ただの便利構文になってしまうのだが,さらに安全な点がある.
if (char buffer[256] = {0};
scanf("%s", buffer)){
// do something
}
ポインタ型を利用するような構文をif init-statementで利用する時,このスコープから外れるだけではなく,破棄されるのである.
以上.