質問

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

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

  • マクロによる RTTI と属性の定義
  • コードを介した RTTI および属性へのアクセス
  • 属性の自動シリアル化
  • 属性の変更をリッスンします (例:値が変更された場合)
役に立ちましたか?

解決

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

XRTTI:

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

OpenC++:

OpenC++ は、C++ フロントエンド ライブラリ (レクサー + パーサー + DOM/MOP) およびソース間トランスレーターです。OpenC++ を使用すると、C++ 言語ツール、拡張機能、ドメイン固有のコンパイラの最適化、およびランタイム メタオブジェクト プロトコルの開発が可能になります。

他のヒント

C++ がリフレクションと出会うと、次のようになります。

C++ meets Reflection

どちらを選択しても、おそらくひどいマクロ、デバッグが難しいコード、または奇妙なビルドステップが含まれることになります。あるシステムが DevStudio の PDB ファイルからシリアル化コードを自動的に生成するのを見たことがあります。

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

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

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

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

MIT ライセンス (以前は LGPL) に基づいて配布されています。

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

私が現在使用しているメンバーを公開するこのアプローチは非常に軽量で、たとえば、シリアル化するクラスを探索したり、「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 << " ";
     }
}

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

私が検討した他の有望な解決策は次のとおりです

  • CAMP と XRTTI/gccxml ですが、どちらも外部ツールの依存関係をプロジェクトに組み込むにはハードルが高いようです。
  • 何年も前、私は Perl を使用していました c2ph/pstruct の出力からメタ情報をダンプするには gcc -gstabs, 、それはあまり煩わしくないですが、私にとっては完璧に機能しましたが、より多くの作業が必要です。

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

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

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

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top