19

ほとんどの成熟した C++ プロジェクトは、独自のリフレクションと属性システムを持っているようです。つまり、文字列でアクセスでき、自動的にシリアル化できる属性を定義するためのものです。私が参加した少なくとも多くの C++ プロジェクトは、車輪の再発明のように見えました。

リフレクションと属性コンテナーをサポートする、C++ 用の優れたオープン ソース ライブラリを知っていますか。具体的には次のとおりです。

  • マクロによる RTTI と属性の定義
  • コードによる RTTI と属性へのアクセス
  • 属性の自動シリアル化
  • 属性の変更をリッスンする (例: OnValueChanged)
4

8 に答える 8

13

まったく異なるアプローチを使用してC++でリフレクションを提供する新しいプロジェクトがあります:CAMPhttps://github.com/tegesoft/camp

CAMPはプリコンパイラを使用せず、classes /properties/関数/...はboost.pythonまたはluabindと同様の構文を使用して手動で宣言されます。もちろん、必要に応じて、gccxmlやopen-c++などのプリコンパイラを使用してこの宣言を生成できます。

これは純粋なC++とブーストヘッダーのみに基づいており、テンプレートメタプログラミングの力のおかげで、あらゆる種類のバインド可能なエンティティをサポートします(たとえば、継承や奇妙なコンストラクターは問題になりません)。

MITライセンス(以前はLGPL)の下で配布されています。

于 2010-06-16T08:24:08.247 に答える
12

これは、C++がReflectionと出会ったときに得られるものです。

C++とReflectionの出会い

どちらを選択しても、恐ろしいマクロ、デバッグが難しいコード、または奇妙なビルド手順が含まれる可能性があります。あるシステムがDevStudioのPDBファイルからシリアル化コードを自動的に生成するのを見てきました。

ただし、真剣に、小さなプロジェクトの場合は、保存/読み込み関数を作成する(またはストリーミング演算子を使用する)方が簡単です。実際、これは大規模なプロジェクトにも当てはまる可能性があります。何が起こっているかは明らかであり、構造が変更された場合は、通常、コードを変更する必要があります。

于 2008-09-17T22:09:55.260 に答える
6

以下の 2 つのツールをご覧ください。私はそれらのどちらも使用したことがないので、それらがどれほど (非) 実用的かはわかりません。

XRTTI :

Xrtti は、C++ の標準ランタイム型システムを拡張するツールおよび付属の C++ ライブラリであり、これらのクラスとそのメンバーを操作するクラスとメソッドに関するより豊富なリフレクション情報を提供します。

OpenC++ :

OpenC++ は C++ フロントエンド ライブラリ (lexer+parser+DOM/MOP) であり、ソースからソースへのトランスレータです。OpenC++ は、C++ 言語ツール、拡張機能、ドメイン固有のコンパイラの最適化、ランタイム メタオブジェクト プロトコルの開発を可能にします。

于 2008-09-17T22:11:01.560 に答える
4

私はこれらのものをかなり長い間見てきましたが、それらは非常に扱いにくい傾向があります。それらは、継承の使用や奇妙なコンストラクターなどの使用を妨げる可能性があります。最終的には、利便性ではなく負担が大きすぎます。

私が現在使用しているメンバーを公開するためのこのアプローチは非常に軽量であり、たとえば、シリアル化のクラスを探索したり、「x」と呼ばれるすべてのフィールドを 0 に設定したりできます。また、静的に決定されるため、非常に高速です。ビルド プロセスの混乱を心配するライブラリ コードやコード生成の層はありません。ネストされた型の階層に一般化されます。

これらのいくつかの書き込みを自動化するために、いくつかのマクロを使用してエディターをセットアップします。

struct point
{
     int x;
     int y;

     // add this to your classes
     template <typename Visitor>
     void visit(Visitor v)
     {
         v->visit(x, "x"); 
         v->visit(y, "y");
     }
};


/** Outputs any type to standard output in key=value format */
struct stdout_visitor
{
     template <typename T>
     void visit(const T& rhs)
     {
         rhs.visit(this);
     }

     template <typename Scalar>
     void visit (const Scalar& s, const char* name)
     {
          std::cout << name << " = " << s << " ";
     }
}
于 2010-03-21T05:09:21.177 に答える
3

これは一般的に C++ 言語の悪名高い弱点です。リフレクションの実装を移植可能にし、価値のあるものにするために標準化する必要があるものが標準ではないからです。呼び出し規約、オブジェクト レイアウト、およびシンボル マングリングが思い浮かびますが、他にもあります。

標準からの指示がないということは、コンパイラの実装者がいくつかのことを異なる方法で行うことを意味します。つまり、移植可能なリフレクション ライブラリを作成する動機を持つ人はほとんどいないということです。つまり、リフレクションを必要とする人は車輪を再発明することになりますが、十分なだけのことです。彼らが必要とするもののために。これは無限に起こりここにいます。

于 2008-09-17T22:00:06.890 に答える
3

これもしばらく眺めた。現在最も簡単な解決策はBOOST_FUSION_ADAPT_STRUCTのようです。コードの最後のセグメントが示すように、実際には、ライブラリ/ヘッダーを取得したら、構造体フィールドを BOOST_FUSION_ADAPT_STRUCT() マクロに追加するだけで済みます。はい、他の多くの人が言及している制限があります。また、リスナーを直接サポートしていません。

私が調べた他の有望な解決策は

  • CAMP と XRTTI/gccxml のどちらも、プロジェクトに外部ツールの依存関係を持ち込むにはハードルのようです。
  • 数年前、私は perl c2ph/を使用pstructして の出力からメタ情報をダンプしgcc -gstabsました。

boost/__cxa のアプローチに関しては、詳細をすべて理解すれば、構造体またはフィールドの追加/変更は簡単に維持できます。現在、これを使用して、dbus の上にカスタム型バインディング レイヤーを構築し、API をシリアル化し、マネージド オブジェクト サービス サブシステムのトランスポート/RPC の詳細を隠しています。

于 2012-09-06T07:56:40.913 に答える
2

一般的なものではありませんが、QT はメタ コンパイラを介してこれをサポートしており、GPL です。QT の人々と話をしてわかったことは、これは純粋な C++ では不可能であり、したがって moc が必要であるということでした。

于 2008-09-17T21:53:47.577 に答える
0

自動イントロスペクション/リフレクション ツールキット。Qt のようなメタ コンパイラを使用し、メタ情報をオブジェクト ファイルに直接追加します。直感的に使いやすい。外部依存関係はありません。自動的に std::string を反映させてから、スクリプトで使用することもできます。IDKにアクセスしてください

于 2014-03-12T12:25:14.820 に答える