web-dev-qa-db-ja.com

C ++構造のすべてのフィールドの値を出力する

単純な構造を考えてみましょう。

struct abc  
{  
    int a;  
    char b;  
}  

構造体として定義された変数に値を取得したので、以下を出力します。

*a = [some value]  
b = [some character]*

遭遇した構造ごとにダンプ...(...)関数を記述せずに、任意の構造に対してこれを実現するための最良の方法は何ですか?

20
Zhinkaas

すでに解決策を見つけているようですが、少し詳しく説明します。

あなたが求めているのはReflectionと呼ばれます。つまり、オブジェクトがそれ自体を記述する能力です。

ほとんどの言語は、メタデータのおかげでリフレクションを実装できます。たとえば、Python)では、オブジェクトの関数と属性はディクショナリ要素に格納されます。

C++には、C#やJavaとは異なり、ネイティブのリフレクションシステムがありません。これにより、(たとえば)この種の自動印刷/シリアル化または逆シリアル化が防止されます。

ただし、C++には非常に強力なメタプログラミングサポートがあり、(テンプレートを使用して)リフレクションを(コンパイル時に)エミュレートできます。これは通常、コンパイル時から実行時へのクロスオーバーを目的としたライブラリである Boost.Fusion を使用して行われます。

リンクに示されている例のように、 BOOST_FUSION_ADAPT_STRUCT マクロを使用すると、標準のstructを取得して、Fusion.Sequenceとして扱われるために必要なインターフェイスを提供できます。

別の例は、 Fusion.Vector または Fusion.Map クラスの属性を格納し、このシーケンスを自動印刷/シリアル化/逆シリアル化メソッドに公開します。

ただし、このシステムには制限があります。メタプログラミングはオブジェクト指向プログラミングとうまく連携しません。

struct Base { char a; };            // Adapt
struct Derived: Base { char b; };   // Adapt

void print(Base const& b) { boost::fusion::for_each<Base>(b, Print()); }

Base(ここではa)のメンバーのみを出力します。ポリモーフィズムを使用する場合は、どこかでvirtualメソッドを使用する必要があります:)

28
Matthieu M.

これを行うには「リフレクション」が必要です。リフレクションは、C++でネイティブに提供されていないか、最小限の情報(タイプID /名前)に対してのみ提供されます。

リフレクション機能を実装するライブラリ( [〜#〜] camp [〜#〜] など)があるため、リフレクションが本当に必要な場合は、それを使用する必要があります。

3
Klaim

C++ではなく、1つはありません。頑張ってください。

2
JSBձոգչ

.NETでC++を使用している場合は、 System.Reflection のものを使用して、構造の内部を調べることができます。ただし、アンマネージC++が、オブジェクトに関するそのようなメタデータを格納することはめったにありません。

0
cHao

これを行うだけです

#include<iostream>
using namespace std;
struct abc  
{  
    int a;  
    char b;  
};
void display(abc myStruct){
   cout << "struct abc {"<< endl;
   cout << abc.a << endl;
   cout << abc.b << endl;
   cout << "}" << endl;
}
int main(){
    abc myStruct
    display(myStruct);
}

リフレクションが必要になるのは、構造体がユーザー定義であり、ユーザーが定義するのではなく、構造体の内部構造がわからない場合のみです。

0
Ashutosh Singh

C++ 17(おそらくC++ 14)といくつかのクレイジーなロシアのハックで-それは部分的に行うことができます。つまり、型の値を順番に出力することはできますが、フィールド名を取得することはできません。

関連するライブラリは、Antony Polukhinの "magic_get" です。具体的には、「フィールドごとに」反復を提供します メカニズム これは、autoパラメータータイプのテンプレート化されたラムダを取ります。例:

struct simple {
    int a;
    char b;
    short d;
};

simple x {42, 'a', 3};
std::stringstream ss;

boost::pfr::for_each_field(
    x,
    [&ss](auto&& val) {
        ss << val << ' ';
    }
);

回答は関連する/重複する質問から移行しました-どういうわけかここで誰もこれに言及しなかったので。

0
einpoklum