VC の pragma

http://lamoo.s53.xrea.com/diary/diary2003b.html

#pragma once 
インクルードガード。#ifndef XXX #define XXX ... #endif と同じ効果。 ガード用マクロ名が被ることがなく、ヘッダのトップに書いておくだけでOK。 
#pragma warning(disable:N) ... #pragma warning(default:N) 
??? はwarningコード。warningレベルは一番高くしておき、無視したいものだけをdisableにするとよい。 C4100(引数未使用)なんかは無視してもかまわないことがほとんどなので。 
#pragma pack(push, N) ... #pragma pack(pop) 
構造体のアラインメントを設定する。さらに static_assert 系と組み合わせると安心。 
#pragma comment(lib, "filename") 
filename で指定したライブラリを自動的にリンクする。 ヘッダに書いておくとインクルードするだけでライブラリが追加でき、プロジェクトの再設定をしなくて済むので楽。 
#pragma comment(linker, "/option:value") 
リンカに対するオプション指定。/defaultlib, /nodefaultlib, /section くらいがあることを知っておけば十分か? 
#pragma message("some text") 
#errorだとコンパイル自体が停止してしまうが、こちらは停止せずにメッセージのみ表示する。 
個人的には、プロパティが大好き。 どうして、C++は、オペレータオーバーロードまで出来るようにして、「ソースコードの見た目」にこだわったのに、プロパティを導入しなかったのかが不思議だよなぁ。

class __declspec(novtable) Class; 
このクラスをabstructだと宣言し、vtable、RTTIなどを取り除く。 テンプレートメタプログラミング系の、大量の中間継承クラスを生成するような状況では効果があるのかもしれない。 *1 
class __declspec(uuid("...")) Class; 
クラスにUUIDを関連付ける。 __uuidof(Class)演算子により、C++型からCOM型(IID)に変換することができる。 
__declspec(property(get=get_Value, put=put_Value)) Type Value; 
プロパティ(記述的にはメンバ変数だが、実際にはget/putメソッドが呼ばれる)を宣言する。 VC++7.xでは、putメソッドが仮想関数で複合代入演算子を用いた場合にコンパイラのバグがあるので注意。 
__declspec(selectany) Type Value; 
リンク時に複数の定義が見つかった場合、自動的に1つだけを残して除去される。 クラス静的変数の場合、変数の定義をcppのほうに書かなくてはいけないが、これを使えばヘッダのみで定義を完結できる。 *2 
__declspec(dllimport), __declspec(dllexport) 
DLLを作成するときに使用する。 
__declspec(noreturn) extern void Function(); 
Function()から帰ってこないことを宣言する。 内部でexit()したり、例外を送出する場合にwarningを抑制できる。 
__declspec(nothrow) Type Function(); 
例外を送出しないことを宣言し、最適化を促す。 C++標準の例外指定:Type Function() throw();と同じ意味。 
他にも naked や thread などがあるけど、そこまで細かいことはしないので使ってません。


--------------------------------------------------------------------------------
*1 : pure virtual function を持つ C++ abstruct class ではこの最適化はしてくれないのだろうか?
*2 : テンプレートクラスの場合は自動的にやってくれるのに……。

2003/11/11 火
◆ VC++の方言を話そう 3/3 - __ (double underscore)
どれもあればあったで便利な機能です。 マクロやテンプレートの応用として使われている機能を言語に組み込もうとするとこういう感じになるのかな?

__interface InterfaceName {}; 
すべてのメソッドが自動的に public pure-virtual とみなされ、メンバ変数を持てないインタフェースを定義する。 インタフェースの宣言としてstructの代わりになるが、クラス内 enum が使えないのが少し不便。 
__super::SuperClassMethod() 
Javaと似たような記述で、親クラスのメソッドを呼べる。 多重継承時も呼び出しが曖昧でない限り使用できる。 WTLなど、どうしてもクラス名が長くなる場合は特に便利。 親クラスのコンストラクタ呼び出しには使えない。 
__if_exists(identifier-name) {}, __if_not_exists(identifier-name) {} 
identifier-name が存在するか否かでコンパイルを分岐する。 いわば、コンパイル時の #ifdef 〜 #endif に相当する。 プリプロセッサの存在意義として最後に残った、コンパイルオプション切り替え機能の置き換えになるかも? テンプレートの特殊化の代わりにこれで誤魔化したり、ヘンなこともできそうではある。 
__uuidof(Type) 
__declspec(uuid)によりTypeに関連付けられたGUIDを取得できる。 
__event, __hook, __unhook, __raise 
詳細は以前の日記を参照。 __hook()の引数は、メンバ関数ポインタではなく「メンバ関数名」であり、またシンクが破棄される前に明示的に__unhook()する必要があるので、いまいち使いづらい。 
__noop(args) 
何もせず、argsも評価されない特殊関数。デバッグのみの処理をリリース時に無効化する場合に使う。 マクロで似たようなことは可能だが、可変長引数関数に関してはこちらのほうが便利。 
__assume(expression) 
expressionが必ず成り立つことを宣言し、最適化を促す。 __assume(0)の形で、「ここには絶対に通らない」ことを示すのが一般的。