2013-03-29 1 views
2

좋아, 우선이 지금까지 작동하지만 매우 버그입니다. ints, floats, doubles, stringschar*s을 사용할 수 있기를 원합니다. 그것은 일종의 char *로 모든 것을 시도하여 일종의지만, 만약 내가 실패하고 싶습니다 그것은 다른 유형으로 그것을 다시 시도 싶습니다. 나는 또한 params의 수를 전달할 필요가 없으면 좋겠다.다양 한 유형의 variadic 함수, threaded cout에 전달

  1. 그들이 충돌 또는 스레드가 다시 참가로 메인 프로그램을 걸려하지 않고 콘솔에 스레드의 출력을 가지고
  2. : 이제

    #include <iostream> 
    #include <cstdlib> 
    #include <sstream> 
    #include <iostream> 
    #include <windows.h> 
    #include <ctime> 
    #include <tchar.h> 
    #include <stdio.h> 
    #include <vector> 
    #include <thread> 
    const enum loglevel{INFO,WARNING,OK,SEVERE}; 
    void logHelperMessage(loglevel,int, ...); 
    void threadedloghelpermessage(loglevel,string); 
    
    int main(int argc, char **argv) 
    { 
        logHelperMessage(INFO,4,"Hi","I","DO","WORK"); 
    } 
    
    void logHelperMessage(loglevel severity,int number, ...) 
    { 
        va_list messages; 
        va_start(messages,number); 
        std::stringstream ss; 
    
        for(int i = 0;i < number;i++) 
        { 
          ss << va_arg(messages,char*); 
        } 
        std::string s = ss.str(); 
        thread t1(threadedloghelpermessage,severity,s); 
        t1.join(); 
    } 
    
    void threadedloghelpermessage(loglevel severity,string message) 
    { 
        //TODO: implement a stack? 
        switch (severity) 
        { 
        case INFO: 
         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE); 
         cout << "[IF]"; 
         break; 
        case WARNING: 
         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x06); 
         cout << "[WA]"; 
         break; 
        case OK: 
         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN); 
         cout << "[OK]"; 
         break; 
        case SEVERE: 
         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED); 
         cout << "[ER]"; 
         break; 
        default: 
         break; 
        } 
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x08); 
        time_t t = time(0); 
        struct tm now; 
        localtime_s(&now, &t); 
        cout << "["; 
        int hour = now.tm_hour; 
        if(hour < 10) 
        { 
         cout << 0 << hour << ":"; 
        } 
        else 
        { 
         cout << hour << ":"; 
        } 
        int minu = now.tm_min; 
        if(minu < 10) 
        { 
         cout << 0 << minu << ":"; 
        } 
        else 
        { 
         cout << minu << ":"; 
        } 
        int sec = now.tm_sec; 
        if(sec < 10) 
        { 
         cout << 0 << sec; 
        } 
        else 
        { 
         cout << sec; 
        } 
        cout << "] "; 
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x07); 
        cout << message << endl; 
    } 
    

    (아래에서 그 이상)에 어쨌든이 (스레드를?)

  3. 사용 : logHelperMessage(logLevel,firstpram,...) (첫 번째 매개 변수를 사용하여 mem 위치를 얻은 다음 거기에서 이동 하시겠습니까?)
  4. : ss << va_arg(messages,char*);에서 작동하지 않으면 char* 가능성이 있습니까?

고급 고급 변수 함수를 둘러 보았지만 모두 인수 수가 많은 부분이 필요합니다. 하나의 유형 만 허용합니다. 또한 연속 루프가 필요한 경우 프로그램의 다른 곳에서 루프를 설정했습니다. (나는 그게 전부라고 생각합니다)

답변

3

C++ 11이 당신을위한 옵션 인 경우 (<thread> 헤더 포함을 고려할 때), use variadic templates instead of C-style variadic functions 수 있습니다.

작업 (이 작동하지 않습니다와 나는 그것을 해결하기 위해 노력하겠습니다 경우 그렇게 말해 줘요, 지금 그것을 테스트 할 수 없습니다)해야이 같은

뭔가 : C에서

template<typename T> 
void insert_messages(std::stringstream& ss, T&& arg) 
{ 
    ss << std::forward<T>(arg); 
} 

template<typename T, typename... Ts> 
void insert_messages(std::stringstream& ss, T&& arg, Ts&&... args) 
{ 
    ss << std::forward<T>(arg); 
    logMessage(std::forward<Ts>(args)...); 
} 

template<typename... Ts> 
void logHelperMessage(loglevel severity, Ts&&... args) 
{ 
    std::stringstream ss; 
    insert_messages(ss, std::forward<Ts>(args)...); 

    std::string s = ss.str(); 
    std::thread t1(threadedloghelpermessage,severity,s); 
    t1.join(); 
} 
+0

하나의 유형의 유모차 만 입력 할 수 있습니까? IE : 모든 문자열 또는 모든 int. –

+0

@StevenVenham : 모든 인수가 같은 유형인지 확인해야합니까? –

+0

아니요, 유형 T 이후로 인수를 취하고 거기에서 사용하는 방법은 무엇입니까? 예를 들어, 내가 통과 한 경우 : "안녕하세요", 1,3.4, '오'라는 말은 여러 다른 유형의 주장을 이해할 수 있습니까? –

1

가변 인자 기능은 다른 유형의 변수를 취할 수 있습니다. 함수 자체는 각 인수가 어떤 유형인지 정확하게 알아야합니다. 예를 들어 printf()를 살펴보십시오. 문자열, 정수, 포인트 등을 전달할 수 있으며 형식 문자열은 함수가 각 변수의 유형을 정확하게 알려줍니다.

인수의 수는 C99의 기능입니다. AFAIK Visual Studio 컴파일러가 지원하지 않습니다.

question에서 C99의 예를 찾을 수 있습니다.

+0

이렇게 나에게 vs2012를 사용하여 그렇게 할 수 없습니까? –

0

을 + +11,이 쉽습니다 :

첫째, 일부 도우미 기능 :

void do_in_order() {}; 
template<typename Lambda0, typename... Lambdas> 
void do_in_order(Lambda0&& L0, Lambdas&&... Ls) { 
    std::forward<Lambda0>(L0)(); 
    do_in_order(std::forward<Lambdas>(Ls)...); 
} 

do_in_order가 null의 람다의 variardic 세트를 취득하고, 순서대로 실행됩니다.

다음, logHelperMessage :

template<typename... Args> 
void logHelperMessage(loglevel severity,Args&&... args) { 
    std::stringstream ss; 

    do_in_order([&](){ 
    ss << std::forward<Args>(args); 
    }...); 
    std::string s = ss.str(); 
    thread t1(threadedloghelpermessage,severity,s); 
    t1.join(); 
} 

및 수행. 무거운 짐을 싣는 일은 대부분 do_in_order에 의해 이루어지며, 여기서 각 arg를 한 번에 하나씩 stringstream에 넣습니다.

개인적으로이 디자인을 사용하지 않을 것입니다. 스레드를 시작하고 곧바로 참여하기 때문에 인라인으로 개선하는 것이 그리 많지 않기 때문입니다.

+0

'template 무효 execute_all (F && ... f) {using T = char []; T { '\ 0', (std :: forward (f)(), void(), '\ 0') ...}; }' –

+0

@Yakk Iv는 bool을 사용하여 스레드가 완료되었는지 여부를 보여주는이 코드를 게시 한 후 일부 코드에 추가되었으며 메시지를 저장하기 위해 벡터 정보를 사용합니다. .join은 if 문 안에 있습니다. –

+0

@LucDanton 예? 그것도 잘 작동합니다. 그것이 작동하는 방법에 대해 더 모호하고, 많은 문자에 대해. :) – Yakk

관련 문제