문제

원래 질문

내가 쓰는 로깅스는 목표를 할 수 있다:

// thread one
Logger() << "Some string" << std::ios::hex << 45;
// thread two
Logger() << L"Some wide string" << std::endl;

현재 내 Logger 헤더 다음과 같이 나타납니다.

#pragma once;
#include <ostream>    
class Logger
{
public:
    Logger();
    ~Logger();

    std::ostream* out_stream;
};

template <typename T>
Logger& operator<< (Logger& logger, T thing) {
    *logger.out_stream << thing;
    return logger;
}

에 대한 몇 가지 메모 이 클래스:

  1. 크로스 플랫폼의 호환성 문제가 되지 않습니다.
  2. 안 Logger.cpp 이 있는 단일 클래스는 관리를 만드는"진짜"ostream.
  3. 로 생성자 및 deconstructor 수행에 필요한 잠금의 단일.

나는 세 가지 문제점:

  • 어떻게 운전자<< 기능 친구 또는 멤버 그래서 나는 설정할 수 있습니다 out_stream 으로 개인?
  • 어떻게 운전자<< 기능 작동을 위한 조작?
  • 어떻게 추가할 수 있습니화되도록 경우 T WCHAR*또는 std::wstring 는 그것을 변환하는 char*또는 std::string 전달하기 전에 out_stream?(나는 할 수 있습니다.을 잃은 높은 유니코드 문자 문제가 되지 않을 수도 있습니다.)

요약의 것을 배운 것에 대한 답:

  • 을 넣어 템플릿을 하기 전에 친구에 대한 후에.
  • std::ios::진수하지 않은 조작.std::진수가 조작.

최종 결과

#pragma once
#include <ostream>
#include <string>

std::string ConvertWstringToString(std::wstring wstr);

class Logger
{
public:
    Logger();
    ~Logger();

    template <typename T>
    Logger& operator<< (T data) {
        *out << data;
        return *this;
    }
    Logger& operator<< (std::wstring data) {
        return *this << ConvertWstringToString(data);
    }
    Logger& operator<< (const wchar_t* data) {
        std::wstring str(data);
        return *this << str;
    }

private:
    std::ostream* out;
};
도움이 되었습니까?

해결책

클래스의 주변 네임 스페이스에서 연산자를 정의하고 연산자 과부하 해상도에만 보이게하는 친구 정의를 사용할 수 있습니다 (:: Operator << ... 구문을 사용하여 수동으로 호출 할 수 없음) :

class Logger
{
public:
    Logger();
    ~Logger();

    std::ostream* out_stream;

    template <typename T>
    friend Logger& operator<< (Logger& logger, T thing) {
        *logger.out_stream << thing;
        return logger;
    }

    /* special treatment for std::wstring. just overload the operator! No need
     * to specialize it. */
    friend Logger& operator<< (Logger& logger, const std::wstring & wstr) {
        /* do something here */
    }

};

대안, 코드를 그대로 유지하고 연산자를 친구로 만들기 위해이 줄을 클래스 정의에 추가하십시오.

template <typename T>
friend Logger& operator<< (Logger& logger, T thing);

조작자 문제의 경우 시간 전에 쓴 코드를 제공하겠습니다.

#include <iostream>
#include <cstdlib>
using namespace std;

template<typename Char, typename Traits = char_traits<Char> >
struct logger{
    typedef std::basic_ostream<Char, Traits> ostream_type;
    typedef ostream_type& (*manip_type)(ostream_type&);
    logger(ostream_type& os):os(os){}
    logger &operator<<(manip_type pfn) {
        if(pfn == static_cast<manip_type>(std::endl)) {
            time_t t = time(0);
            os << " --- " << ctime(&t) << pfn; 
        } else
            os << pfn;
        return *this; 
    }
    template<typename T> 
    logger &operator<<(T const& t) { 
        os << t; 
        return *this;
    }
private:        
    ostream_type & os;
};

namespace { logger<char> clogged(cout); }
int main() { clogged << "something with log functionality" << std::endl; }

};

std :: hex이지만 std :: ios :: hex는 아닙니다.. 후자는 setf 스트림의 기능. 예를 들어, 조작기의 특별한 처리는 필요하지 않습니다. std :: endl이 사용될 때 시간을 스트리밍하기 때문에 std :: endl의 위의 특별한 처리는 필요합니다.

다른 팁

템플릿을 사용하는 것은 올바른 방법이지만 템플릿이 헤더 파일 (파일logger.h, 또는 당신이 부르는 것), ~ 아니다 구현 파일에서 (logger.cpp). 이것은 가지고있는 모든 유형에 대해 자동으로 작동합니다 operator << 로 정의되었습니다 std::ostream. 또한 스트림 조작기 객체와 자동으로 작동합니다. std::ostream 매개 변수 및 operator << 그냥에서 함수를 호출합니다 ostream.

당신은 할 수 있습니다 operator << 다음과 같이 친구 기능 :

template <typename T> friend Logger& operator<< (Logger& logger, T thing);

전문화는 쉽습니다 - 템플릿 전문화 만 사용합니다 (다시 헤더 파일에서) :

template <typename T>
Logger& operator<< (Logger& logger, T thing) {
    *logger.out_stream << thing;
    return logger;
}

// Template specialization - the "template <>" part is necessary
template <>
Logger& operator<< (Logger& logger, const wchar_t *wstr)
{
  // convert wstr to an ANSI string and log it
}

template <>
Logger& operator<< (Logger& logger, const std::wstring & wstr)
{
  // convert wstr to an ANSI string and log it
}

우정 선언이 필요하지 않습니다.

class Logger
{
public:
    Logger();
    ~Logger();

template <typename T>
inline Logger& Display(T thing)
{
   *out_stream << thing;
    return *this;
}
private:
    std::ostream* out_stream;
};

template <typename T>
Logger& operator<< (Logger& logger, T thing) 
{
    return logger.Display(thing);
}

왜 printf 방법과 사용하여 다 매개변수법(으로 세 가지 점...).이것은 여전히 당신의 많은 포맷 전원 및 나던 그는 혼란으로 사용하는 경우 <<.

예를 들어:

Logger("This is my log msg %0X", 45);

에 걸 두 초고 병를 당겨하는 코드 샘플습니다.

편집:

void Logger(const char* format, ...)
{
    char szMsg[3000];

    va_list args;
    va_start( args, format );
    vsnprintf( szMsg, sizeof(szMsg) - 1, format, args );
    va_end(args);

    // code to print szMsg to a file or whatever here
}

를 사용하려면 이로 클래스지 기능을 수 있는 하중 초과 로 operator()-그것은 동

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