web-dev-qa-db-ja.com

関数名__func__の定義済みマクロ

ファイル、行、およびログメッセージの呼び出し元の関数を記録するデバッグログメッセージ関数を作成しようとしています。

#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__ に使える?
22

__func__はマクロであると想定していますが、そうではありません。これは、条件付きでサポートされている事前定義の識別子であるため、#if definedまたは#ifdefを使用してチェックすることはできません。

コンパイラーがこれがサポートされているかどうかを通知する方法がない場合(_FUNC_SUPPORTEDまたは何かを介して可能です。実際にこれを行っているとは言いません)、実際の代わりにコンパイラーを確認する必要があります。識別子。

線に沿った何か:

#ifndef __FUNCTION_NAME__
    #ifdef WIN32   //WINDOWS
        #define __FUNCTION_NAME__   __FUNCTION__  
    #else          //*NIX
        #define __FUNCTION_NAME__   __func__ 
    #endif
#endif
25
Luchian Grigore

しばしば BoostBOOST_CURRENT_FUNCTION<boost/current_function.hpp>で定義されたクロスプラットフォームソリューションです。

12
Jean Davy

これらは、__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
7
alexfontaine

__FUNCTION__マクロがGCCとMSVCの両方に定義されていることを追加したいと思います。標準ではありませんが、両方のコンパイラで使用できます。

GCC標準の定義済みマクロ 引用:

C99は__func__を導入し、GCCは長い間__FUNCTION__を提供してきました。これらはどちらも現在の関数の名前を含む文字列です(わずかな意味上の違いがあります。GCCのマニュアルを参照してください)。どちらもマクロではありません。プリプロセッサは現在の関数の名前を知りません。ただし、__FILE__および__LINE__と組み合わせて使用​​すると便利です。

MSVC定義済みマクロ 引用:

__FUNCTION__

関数でのみ有効です。囲んでいる関数の装飾されていない名前を文字列リテラルとして定義します。

/ EPまたは/ Pコンパイラオプションを使用する場合、__FUNCTION__は展開されません。

例については、__FUNCDNAME__を参照してください。

したがって、両方のコンパイラが実装しているため、__FUNCTION__を使用しても問題ありません。両方のコンパイラで同じ結果が得られない場合もありますが、状況によってはそれで問題ない場合もあります。

6
nonsensickle