2017-04-20 8 views
1

나는 예쁜 프린터를 제공하는 std :: objects 집합을 포함하는 클래스의 예쁜 프린터를 작성하려고합니다. 나는 꽤 인쇄 클래스 "FooContainer"의 객체를 할 수 있도록하려는GDB : STL 컨테이너가 포함 된 Pre-Print 클래스

#include <set> 
#include <iostream> 
#include <cassert> 

class Foo { 
public: 
    int x; 

    bool operator<(const Foo & rhs) const { 
    return this->x < rhs.x; 
    } 
}; 

class FooContainer { 
public: 
    std::set<Foo> content; 
}; 

int main(int argc, char **argv) { 
    FooContainer c; 
    Foo f1 {1}; 
    Foo f2 {2}; 
    c.content.insert(f1); 
    c.content.insert(f2); 

    assert(false); // hand over to gdb 
} 

: 아주 기본적으로,이 같은 내 C++ 코드는 모습입니다. 그래서, 나는이처럼 어떻게 든 보면 꽤-프린터 원하는 :

class FooPrinter(object): 
    def __init__(self, val): 
     self.val = val 

    def to_string(self): 
     return "X: " + str(self.val['x']) 

class FooContainerPrinter(object): 
    def __init__(self, val): 
     self.val = val 

    def to_string(self): 
     res = "" 
     for foo in self.val['content']: 
      res += " " + FooPrinter(foo).to_string() 
     return res 

을하지만를, 이러한 노력 GDB는 나에게 오류를 제공하십시오 FooContainerPrinter는 내부 구성원에 액세스 할 수 있습니다처럼

(gdb) p c 
Python Exception <class 'TypeError'> 'gdb.Value' object is not iterable: 
$7 = 

같습니다 std :: set 중 하나이므로 반복 할 수 없습니다. 정말은 그 표준 뒤에있는 붉은 검정 트리를 가로 질러 다니는 것을 피하고 싶습니다. : 나 자신을 설정하십시오. 이것을 달성하기위한 깔끔한 트릭이 있습니까?

답변

0

몇 가지 시도를 한 후에 매우 가까운 방법을 발견했습니다. 기본적으로 stdlib과 함께 제공되는 기본 StdSetPrinter를 사용하고 있지만 인쇄용으로 사용하지는 않습니다. 집합을 반복하기 위해서입니다. 내 코드는 이제 다음과 같습니다

from libstdcxx.v6.printers import StdSetPrinter 

class FooPrinter(object): 
    def __init__(self, val): 
     self.val = val 

    def to_string(self): 
     return "X: " + str(self.val['x']) 

class FooContainerPrinter(object): 
    def __init__(self, val): 
     self.val = val 

    def to_string(self): 
     return "My Foo Container" 

    def children(self): 
     pp = StdSetPrinter("dummy", self.val['content']) 
     return pp.children() 

지금, 기본 꽤 인쇄 마법 여전히 상용구 (기본적으로는 출력 "내 푸 컨테이너 = {& langle가, rangle 내용 및 꽤 인쇄; ...}을 (를)") 추가 그러나 그것은 나와 잘 맞습니다. 나는 심지어 이 아니라고 생각한다.은 자신의 children()을 정의하지만, to_string() 내부에서는 pp.children()을 사용하므로 출력 문자열을 완전히 제어 할 수있다.

libstdC++에서 기본 예쁜 프린터를 배치하는 경로가 PYTHONPATH에 있어야한다는 단점이 있습니다.

1

원하는대로 정확하게 수행 할 수있는 방법이 없습니다. 주요한 문제는 예쁜 인쇄 API가 의도적으로 단순하게 유지 되었기 때문에 (아마도 너무 간단 함) 컨테이너를 따로 선택할 수있는 프로그래밍 방식을 제공하지 않는다는 것입니다. 인쇄 할 때 필요한 것만 제공합니다. 덜 일반적입니다.

그러나이 경우 가능한 한 접근법은 프린터 std::set입니다.

즉, FooContainer 프린터를 놓고 Foo 프린터로 작성하면됩니다. FooContainer은 기본 gdb 스타일을 사용하여 인쇄되고 동봉 된 std::set은 libstdC++ 프린터를 사용하여 표시되며 각 요소는 Foo 프린터를 사용하여 표시됩니다.

전체 내용을 하나의 긴 문자열로 인쇄하려면 std::set 프린터를 찾아서 코드를 추출해야합니다.

+0

Tom의 마지막 점에 대해서는'RbtreeIterator' 타입 (트리의 모든 노드에 대해 GCC의 RB 트리를 파이썬 iterables로 바꾼 타입)과 이름에서 알 수있는'get_value_from_Rb_tree_node' 함수를 참조하십시오. 아마 코드를 추출 할 필요가 없습니다. 코드를 다시 사용하십시오. 나는 희망. –

+0

libstdC++에 변경 사항이있을 경우 향후 코드가 변경 될 수 있다는 경고와 함께 좋은 생각입니다. 나는이 코드가 편리한 헬퍼 클래스를 사용한다는 것을 잊었다. –

+0

해답을 주셔서 감사합니다. 그러나 기본 프린터를 하이재킹하여 원하는 작업을 수행 할 수있는 방법을 발견했다고 생각합니다. 자세한 내용은 내 대답을 참조하십시오. –