にゃははー

はへらー

C++11 Advent Calendar 2011 9日目

ここ数日の怒涛のエントリで精魂尽き果てている感じなので内容は薄いです。あしからず。

注:C++11 Advent CalendarとなっていますがかねないのでISO/IEC 14882:2011は持ってないです。なので運よく手に入れることが出来たn3290を使っています。

Pragma operator

C++11からPragma operatorというのが追加されました。これは今までのPragma directiveと同等の機能を提供するなにかです。
なにかですって言ってる理由は、これは規格上Preprocessing directivesに分類されていて、かつキーワード(2.12)にもoperator(2.13)にも入っていないからです。なんて言ったらいいんでしょう...

ちなみにPragma operator, Pragma directive共にPreprocessing directivesに分類されてますが、プリプロセス時に処理されるとは限らないので注意。
プリプロセッサが処理できないPragmaはそのままスルーされたりします。

例えばGCCでは、プリプロセッサが処理できないPragma operatorはPragma directiveに展開されてコンパイラに投げられます。コンパイラでも処理できないければそこでエラーになるなり警告が出たりします。

Pragma operatorは以下のformを持ちます。

_Pragma ( string-literal )

string-literalは正しくstring-literalである必要があります。constexprとかはダメです。当たり前ですね。規格上Preprocessing directivesに分類されてるのだから。

omp parallel

じゃぁPragma operatorがあって何が嬉しいのかと思うのかもしれないですが、今までPragma directiveを使ってたコードがかなり整理できると思います。

例えばOpenMPは有効になっている場合、_OPENMPラベルが定義されることになっています。今までのコードが、

#if defined(_OPENMP)
#  pragma omp parallel
{
#endif
...
#if defined(_OPENMP)
#  pragma omp for
#endif
for ( ... )
{
	...
}
...
#if defined(_OPENMP)
}
#endif

とかあってみてくださいよ。

まずPragma operatorを使いましょう。大体方向性が分かってもらえるだろうか。
一気に書かないのは行数稼ぐとかそう言うのではないです。おいそこ稼いでるとか言うな。

#if defined(_OPENMP)
_Pragma("omp parallel")
{
#endif
...
#if defined(_OPENMP)
_Pragma("omp for")
#endif
for ( ... )
{
	...
}
...
#if defined(_OPENMP)
}
#endif

あとはマクロ使ってやると綺麗になります。行数は増えますがメンテナンス性とかよくなるはずです。だから稼いでるとかいうn

#if defined(_OPENMP)
#  define PRAGMA_(x) _Pragma(#x)
#  define OMP(x) PRAGMA_(omp x)
#  define OMP_BEGIN_PAREN(x) OMP(x) {
#  define OMP_END_PAREN }
#else
#  define OMP(x)
#  define OMP_BEGIN_PAREN(x)
#  define OMP_END_PAREN
#endif

OMP_BEGIN_PAREN(parallel)
...
OMP(for)
for( ... )
{
	...
}
...
OMP_END_PAREN

はうぁ〜きれいになりましたです〜

ある機能がサポートされているかどうかとかをいろいろな箇所で分散して行うと漏れていたりするので一箇所でまとめて、かつサポートされていようがされていまいがどちらでも使えるように整形するのがマクロを使う一番の理由じゃないですかね。

繰り返しが嫌だというのもわからないでもないですが、それはtemplateとか使ってやったほうが明らかにoptimizerがうまく処理できたりします。

力尽きたとか言わないこと。

以上。