2014-11-06 11 views
10

ostream & 매개 변수 o을 사용하여 해당 ostream에 쓰는 함수가 있다고 가정합니다. operator << 구현이 좋은 예입니다.다른 streambuf를 사용하여 임시 ostream을 생성해야합니까?

ostream& operator << (ostream& o, const MyThing& t) 
{ 
    // ... interesting code here ... 
    return o; 
} 

이 함수 내에서 스트림에 서식 옵션을 지정하고자 할 수 있습니다. 예를 들어, 함수에 전달 될 때 o이 구성되는 방법에 관계없이 숫자를 16 진수로 인쇄하려고 할 수 있습니다.

둘째, 현재 서식 플래그에 대한 가정을 할 수 있기를 바랍니다. 예를 들어, 달리 요구하지 않는 한 숫자가 십진수로 포맷되었다고 가정 할 수 있으면 좋을 것입니다.

마지막으로 함수가 종료 될 때까지 o의 서식 옵션을 호출하기 전에 있던 것과 동일하게하여 호출자에게 변경되지 않도록합니다. 이것은 단순히 발신자에게 공손한 문제입니다.

은 지금까지 나는 함수 내에서 로컬 ostringstream를 생성하고 (서식 설정 옵션을 포함)이 내 모든 일을하고, 함수의 끝에서 o.str()을 보내이를 달성했다. StackOverflow 질문 here은 나보다 더 똑똑한 사람들이 동일한 접근 방식을 취한다고 제안합니다. 그러나 나는 문자열에 문자열 (문자열)이 꽤 빨리 나올 수 있으므로 이전에 출력으로 보낼 수있는 너무 많은 데이터를 유지한다고 걱정합니다.

1)가, 법률 관용적인가, 좋은 형태 o.rdbuf() 주위 임시 (스택 기반) ostream에를 만들고 해당 ostream에 내 일을 할 수있는 :

나는이 개 질문이? 내 자신의 테스트와 페이지에서 cppreference.com 내가 할 수있는 것으로 나타납니다.

ostream& operator << (ostream& o_, const MyThing& t) 
{ 
    ostream o (o_.rdbuf()); 
    // write stuff to "o", 
    // setting formatting options as I go. 
    return o_; // Formatting on the parameter ostream o_ unchanged. 
} 

2) 제가 고려하지 않은 다른 방법이 있습니까?

답변

0

설정은 iostream에 포함 된 ios라는 클래스에 정의 된 fmtflags 객체라는 유형의 객체에 저장할 수 있습니다. 이러한 개체 중 하나를 선언 할 수 있지만 범위 확인 연산자를 사용하여 선언해야합니다.

다음 문은 변수 old_settings의 형식 상태의 특정 측면을 저장합니다 :

ios::fmtflags old_settings = cout.flags(); 

그런 다음, 새 설정을 사용하여 출력을 수행 한 후, 당신은 이전 설정을 복원 할 수 있습니다와 같은 함수를 호출하여 이전 설정을 인수로 사용 :

cout.flags(old_settings); 

다른 설정은 멤버 함수를 사용하여 가져오고 복원 할 수 있습니다. 예를 들어

int old_precision = cout.precision(); 

은 현재 정밀도 사양을 저장합니다.그런 다음

cout.precision(old_precision); 

+0

그 호출이 가장 생성자 및 소멸자에 배치 될 것 일부 스택 기반 객체. Boost 클래스가하는 일이라고 생각합니다. – peterpi

2

Boost IO State Savers는이 목적을 위해 정확히 내장 된 원래 값으로 정밀도를 복원합니다.

1

그건 나쁜 해결책이 아닙니다. 그것은 확실히 합법적입니다. 나는 이 너무 일반적이라고 생각하지 않습니다. 따라서 에 대해 논평하는 것이 좋습니다.

내가 여기에 본 적이 가장 흔한 해결책은 당신이 생성자에서 (일반적으로, flags(), precision()fill())를 필요로하는 상태를 모두 절약 할 수있는 상태 보호기 클래스를 만들고, 그것을 복원하는 것입니다 소멸자, 그리고 나서 에 강제로 원하는 모든 옵션을 설정하십시오. (이에 대한 copyfmt를 사용하는 가능할 수도 있지만 등이 또한 복사 것을 당신은 아마 놀고 싶어하지 않는 예외 마스크.)