이것은 매크로에서 가능한 사용 일방시스입니까? 템플릿으로 변환 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/419559

문제

괜찮은 로깅을 위해 Clogclass를 구현 한 후에는 매크로를 정의했지만 하나의 매개 변수와 함께 작동합니다 ...

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

글쎄, 그것은 2 개 이상의 매개 변수로 호출되면 실패합니다.

편집 : Variadic 매크로는 2005 년 대에 도입되었습니다 (그러나 현재 vs 2003에 있습니다 ...). 조언이 있습니까?

도움이 되었습니까?

해결책

MyLog 매크로가 변수 수의 인수를 취하는 사용자 정의 functor 객체를 반환 할 수 있습니다.

#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;
}

다른 팁

귀하의 질문은 실제로 두 가지 답변에 호소합니다. Printf와 같이 작동하지만 완전히 사용자 정의 할 수있는 범용 로깅 기능을 수행하려고합니다. 그래서 당신은 필요합니다 :

  • 가변 수의 인수를 취하는 매크로
  • 변수 수의 인수를 취하는 함수

다음은 ADATAPTED CODE 예제입니다.

#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로 성공적으로 테스트했습니다.

기능에 대한 변동성 주장은 영원히 존재 했으므로 여기에 계산 가능성에 대해 걱정하지 않았습니다.

일부 템플릿 메타 프로그램으로 수행 할 수는 있지만 위의 코드의 단순성을 감안할 때 관심을 보지 못했습니다.

마지막으로, 왜 기능 대신 빈 클래스에서 정적 메소드를 사용합니까?

class Log {
    stringstream buffer;
    public:
        class Proxy {
            public:
                Proxy(Log& p) : parent(p) {}
                template<class T>
                Proxy& operator,(T const& t) {
                    parent.buffer << t;
                    return *this;
                }
                ~Proxy() {
                    parent.buffer << endl;
                    cout << parent.buffer.str();
                    parent.buffer.str("");
                }
            private:
                CLog& parent;
        };

        template<class T>
        Proxy operator<<(T const& t) {
            buffer << t;
            return Proxy(*this);
        }
};

타임 스탬프를 작성하고 로그 레벨을 확인하고 파일에 쓰기 등을 위해 사소하게 확장 될 수 있습니다.

또는 더 간단하지만 덜 유연하게 :

class Log {
    public:
        class Proxy {
            public:
                template<class T>
                Proxy& operator,(T const& t) {
                    cout << t;
                    return *this;
                }
                ~Proxy() {
                    cout << endl;
                }
        };

        template<class T>
        Proxy operator<<(T const& t) {
            cout << t;
            return Proxy();
        }
};

용법:

Log log;
void f() {
     log << "hey, my age is ", age;
}

이 인스턴스에서 매크로가 아닌 전역으로 보이는 외부 함수를 사용하는 경향이 있으며 VA_LIST를 사용 하여이 함수의 엘립스 시스를 해결하는 경향이 있습니다. 내 이전 게시물을 참조하십시오 이를 달성하는 방법에 대한 예.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top