4

適切なロギングを行うために CLogClass を実装したので、マクロも定義しましたが、1 つのパラメーターでしか機能しません...

class CLogClass
{ 
public:
       static void DoLog(LPCTSTR sMessage, ...);
};
#define DebugLog(sMessage, x) ClogClass::DoLog(__FILE__, __LINE__, sMessage, x)

まあ、2つ以上のパラメータで呼び出されると失敗します:( ...それを回避することはまったく可能ですか?どうにかしてテンプレートに変換できますか?

編集: Variadic マクロは VS 2005 で導入されました (しかし、私は現在 VS 2003 にいます...)。何かアドバイスはありますか?

4

4 に答える 4

6

可変数の引数を取るカスタム ファンクター オブジェクトを返す MYLOG マクロを作成できます。

#include <string>
#include <cstdarg>

struct CLogObject {

  void operator()( const char* pFormat, ... ) const {
    printf( "[%s:%d] ", filename.c_str(), linenumber );
    va_list args;
    va_start( args, pFormat );
    vfprintf( stderr, pFormat, args );
    va_end( args );
  }

  CLogObject( std::string filename, const int linenumber )
    : filename( filename ), linenumber( linenumber )
  {}
  std::string filename;
  int linenumber;
};

#define MYLOG CLogObject( __FILE__, __LINE__ )


int _tmain(int argc, _TCHAR* argv[])
{

  MYLOG( "%s, %d", "string", 5 );
  return 0;
}

この回答に触れたタイプセーフバリアントにステップオーバーするのはそれほど難しくないことに注意してください。の連鎖効果により、可変引数は必要ありませんoperator<<

struct CTSLogObject {

  template< typename T >
  std::ostream& operator<<( const T& t ) const {
    return std::cout << "[" << filename << ":" << linenumber << "] ";
  }

  CTSLogObject( std::string filename, const int linenumber )
    : filename( filename ), linenumber( linenumber )
  {}
  std::string filename;
  int linenumber;
};
#define typesafelog CTSLogObject( __FILE__, __LINE__ )

int _tmain(int argc, _TCHAR* argv[])
{
  typesafelog << "typesafe" << ", " << 5 << std::endl;
  return 0;
}
于 2009-01-07T10:05:19.843 に答える
4

あなたの質問は、実際には 2 つの回答に訴えます。printf のように機能しますが、完全にカスタマイズできるユニバーサル ロギング機能を実行したいと考えています。したがって、次のものが必要です。

  • 可変数の引数を取るマクロ
  • 可変数の引数を取る関数

適応したコード例を次に示します。

#include <stdio.h>
#include <stdarg.h>


class CLogClass
{
public:
    static void DoLogWithFileLineInfo( const char * fmt, ... )
    {
        va_list ap;
        va_start( ap, fmt );
        vfprintf( stderr, fmt, ap );
        va_end( ap );
    }

};


#define MYLOG(format, ...) CLogClass::DoLogWithFileLineInfo("%s:%d " format , __FILE__, __LINE__, __VA_ARGS__)

int main()
{
    MYLOG("Hello world!\n", 3); // you need at least format + one argument to your macro
    MYLOG("%s\n", "Hello world!");
    MYLOG("%s %d\n", "Hello world!", 3);
}

Variadic マクロは C99 で導入されたため、C99 または C++0x をサポートするコンパイラで動作します。gcc 3.4.2 と Visual Studio 2005 で正常にテストしました。

関数への可変個引数はずっと存在していたので、ここでは互換性について心配する必要はありません。

テンプレートのメタプログラミングでそれを行うことはおそらく可能ですが、上記のコードの単純さを考えると、それが興味深いとは思いません。

最後のメモとして、関数の代わりに空のクラスで静的メソッドを使用するのはなぜですか?

于 2009-01-07T08:54:16.897 に答える
0

この場合、マクロではなくグローバルに表示される extern 関数を使用し、va_list を使用してこの関数の省略記号を解決する傾向があります。これを達成する方法の例については、私の以前の投稿を参照してください。

于 2009-01-07T08:41:39.670 に答える