ファイル、行、およびログメッセージの呼び出し元の関数を記録するデバッグログメッセージ関数を作成しようとしています。
#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __func__ , __FILE__, __LINE__ );
上記のコードは一部のコンパイラでは機能しますが、すべてでは機能しません。私のコードは、GCCおよびMicrosoft Visual Studioと相互互換性がある必要があります。互換性を維持するために、以下の定義を追加しました。
#ifndef __FUNCTION_NAME__
#if defined __func__
// Undeclared
#define __FUNCTION_NAME__ __func__
#Elif defined __FUNCTION__
// Undeclared
#define __FUNCTION_NAME__ __FUNCTION__
#Elif defined __PRETTY_FUNCTION__
// Undeclared
#define __FUNCTION_NAME__ __PRETTY_FUNCTION__
#else
// Declared
#define __FUNCTION_NAME__ "N/A"
#endif // __func__
#endif // __FUNCTION_NAME__
#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __FUNCTION_NAME__, __FILE__, __LINE__ );
上記のコードスニペットの問題は、#elseマクロがすべてのコンパイラでアクティブであり、他のマクロはアクティブでないことです。言い換えると #if defined __func__
は、__func__
は定義済みマクロです。
私の質問は
__func__
に使える?__func__
はマクロであると想定していますが、そうではありません。これは、条件付きでサポートされている事前定義の識別子であるため、#if defined
または#ifdef
を使用してチェックすることはできません。
コンパイラーがこれがサポートされているかどうかを通知する方法がない場合(_FUNC_SUPPORTED
または何かを介して可能です。実際にこれを行っているとは言いません)、実際の代わりにコンパイラーを確認する必要があります。識別子。
線に沿った何か:
#ifndef __FUNCTION_NAME__
#ifdef WIN32 //WINDOWS
#define __FUNCTION_NAME__ __FUNCTION__
#else //*NIX
#define __FUNCTION_NAME__ __func__
#endif
#endif
しばしば Boost は BOOST_CURRENT_FUNCTION
が<boost/current_function.hpp>
で定義されたクロスプラットフォームソリューションです。
これらは、
__FILE__ and __LINE__
のようなプリプロセッサマクロでも変数でもありません。
次のリンクから取得:
http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Names.html
また、あなたの質問に似ている、回答済みの他の質問も確認してください。
__ PRETTY_FUNCTION__を使用できるかどうかを確認する方法
例:
#ifdef _MSC_VER // Visual Studio
#define FUNCTION_NAME __FUNCTION__
#endif
__FUNCTION__
マクロがGCCとMSVCの両方に定義されていることを追加したいと思います。標準ではありませんが、両方のコンパイラで使用できます。
GCC標準の定義済みマクロ 引用:
C99は
__func__
を導入し、GCCは長い間__FUNCTION__
を提供してきました。これらはどちらも現在の関数の名前を含む文字列です(わずかな意味上の違いがあります。GCCのマニュアルを参照してください)。どちらもマクロではありません。プリプロセッサは現在の関数の名前を知りません。ただし、__FILE__
および__LINE__
と組み合わせて使用すると便利です。
MSVC定義済みマクロ 引用:
__FUNCTION__
関数でのみ有効です。囲んでいる関数の装飾されていない名前を文字列リテラルとして定義します。
/ EPまたは/ Pコンパイラオプションを使用する場合、
__FUNCTION__
は展開されません。例については、
__FUNCDNAME__
を参照してください。
したがって、両方のコンパイラが実装しているため、__FUNCTION__
を使用しても問題ありません。両方のコンパイラで同じ結果が得られない場合もありますが、状況によってはそれで問題ない場合もあります。