2017-03-05 3 views
1

관련 코드는 다음과 같습니다컴파일러가 반환하는 템플릿 유형 추론 할 수

std::fstream fout("Logs.txt"); 
class Logs; 
typedef std::ostream& (*ostream_manipulator2)(std::ostream&); 
class LogsOutput 
{ 
public: 
    LogsOutput() {} 
    ~LogsOutput() {} 
    Logs * pLogs; 
    friend LogsOutput& operator<<(LogsOutput &logsClass, std::string &strArg); 
    friend LogsOutput& operator<<(LogsOutput &logsClass, const char *strArg); 
    friend LogsOutput& operator<<(LogsOutput &logsClass, ostream_manipulator2 pf); 
    friend LogsOutput& operator<<(LogsOutput &logsClass, uint64_t number); 
}; 
LogsOutput *pLogsOutput; 
template <typename T> 
T& LOUToutput() 
{ 
        if (pLogsOutput) 
        { 
         return (*pLogsOutput); 
        } 
        else 
         return fout; 
} 

내가 같은이 함수를 호출하고 싶은 다음 LogsOutput 클래스가 만들어지지 않습니다 때때로 그러나

LOUToutput() << "Print this line " << std::endl; 

을, 따라서 포인터를 dereferencing 어떤 경우 파일 대신 오히려 출력 것이라고 추락 것입니다. 컴파일러가 컴파일시에 LogsOutput 클래스가 인스턴스화되는지 여부를 알 수 없으므로 템플릿 유형을 추론 할 수 없다는 것을 알지만, 작동시킬 수있는 다른 방법은 보이지 않습니다. 내 질문에 어떻게 내 함수를 런타임 조건에 따라 다른 형식을 반환 할 수 있습니다?

+0

런타임에 유형을 구분해야하는 경우, 당신은 슈퍼 클래스를 반환하는 함수를 만드는 것으로 간주해야을, 관심이있는 런타임 조건에 따라 런타임에 해당 클래스의 두 하위 클래스 중 하나를 반환할까요? 템플릿 인스턴스화는 컴파일 타임에 발생하며 클래스의 특정 유형을 기반으로 호출 할 가상 메소드의 구현이 런타임에 수행됩니다. – AustinZ

답변

2

이 복잡한 솔루션은 상속을 사용하는 것입니다. std :: ostream에서 상속받는 경우 공통 기본 클래스를 반환 할 수 있습니다 (여기에 관심있는 토론이 있습니다 : How to inherit from std::ostream?)

더 간단한 솔루션 인 imo.는 출력을 리디렉션하는 프록시 클래스를 반환합니다. 필요에 따라

struct LogProxy { 
    LogsOutput *pLog; 
    // ... 
    LogProxy &operator<<(std::string &o) { 
     if(pLogsOutput) { 
      *pLog << o; 
     } else { 
      // Assuming this is available as a global.. You probably don't want to do that 
      fout << o; 
     } 
     return *this; 
    } 
    // .... 
}; 

LogProxy LOUToutput() { 
    return LogProxy { pLogsOutput; }; 
} 

다른 몇 가지 일반적인 의견 : 당신이 템플릿을 사용하려면

  1. 이 컴파일 시간 조건을 만들 필요가있다. std :: enable_if <과 같은 것을 사용하면 에서 선택할 수있는 LOUToutput()의 여러 템플릿 오버로드를 제공 할 수 있습니다. 시간은 어디로 로그인해야합니까?

  2. 나는 단지 SO에 게시하기위한 목적이라고 생각하지만 코드에는 헤더 파일에 선언 된 여러 개의 전역 변수가 있습니다. 문제를 해결해야합니다.

  3. 코드에 const 선언이 없습니다. 이러한 연산자는 출력 (문자열, .etc.) 매개 변수에 적어도 const로 선언해야하는 것처럼 보입니다.

편집 : 다음 작업은이 아이디어의 샘플 (제대로 컴파일) :

#include <iostream> 

struct PRXY { 
    bool cond; 

    const PRXY &operator<<(const std::string &t) const { 
     if(cond) { 
      std::cout << t; 
     } else { 
      std::cerr << t; 
     } 
     return *this; 
    } 
}; 

PRXY pr(bool cond) { 
    return PRXY { cond }; 
} 

void test() { 
    pr(false) << "Hello"; 
} 
+0

감사합니다.이 프록시 아이디어가 잘 작동했습니다. – user

관련 문제