2017-04-20 7 views
1

私は自分自身のかなりのプリンタを提供しているオブジェクトのstd :: setを含むクラス用のきれいなプリンタを作成しようとしています。私はかなり-印刷クラス「FooContainer」のオブジェクトをできるようにしたいGDB:STLコンテナを含むPretty-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の値を返します。それを反復することはできません。 本当には、その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() 

、デフォルトかなり印刷魔法はまだ(基本的には出力「私はFooコンテナ= {...&langleを、コンテンツ&rangleのプリティプリント; ...}」)いくつかの定型を追加しますそれは私と一緒には問題ありません。私はそれがでもは、独自のchildren()を定義するのではなく、to_string()内のpp.children()を使用して、出力文字列を完全に制御できることもできると思います。

libstdC++がデフォルトのかわいいプリンタを置くパスがPYTHONPATHにある必要があるという欠点があります。

1

あなたが望むものを正確に行うための良い方法はありません。主な問題は、きれいに印刷されたAPIが意図的にシンプルに保たれていて(おそらく少し単純すぎるため)、プログラマブルな方法でコンテナを選別することができず、印刷に必要なものだけを提供しますあまり一般的ではない。

しかし、この状況では、実行可能なアプローチの1つがstd::setプリンタに委ねられている可能性があります。

つまり、FooContainerプリンタを落として、Fooプリンタを作成するだけです。 FooContainerはデフォルトのgdbスタイルで印刷され、囲まれたstd::setはlibstdC++プリンタを使用して表示され、個々の要素はFooプリンタを使用して表示されます。

実際には1つの長い文字列として内容全体を印刷したい場合は、std::setプリンタを掘り出してコードを抽出する必要があります。

+0

Tomの最後の点については、 'RbtreeIterator'型(GCCのRBツリーをツリー内のすべてのノードでPython iterablesに変える)とその名前が意味する' get_value_from_Rb_tree_node'関数を参照してください。おそらく、それらからコードを抽出する必要はなく、再利用するだけです。私は願います。 –

+0

これは良い考えです。将来libstdC++に変更があった場合、あなたのコードに適応する必要があるという警告があります。私はこのコードが便利なヘルパークラスを使用していたことを忘れていました... –

+0

答えをありがとう。しかし、私は、デフォルトのかわいいプリンタをハイジャックして、私が望むことをやり遂げる方法を見つけたと思う。詳細は私の答えを見てください。 –

関連する問題