何百ものメッセージタイプを持つ何らかのプロトコルがあるとしましょう。各メッセージタイプはC++クラスでモデル化したいと考えています。「注釈付き」フィールドを持つクラスを設計するにはどうすればよいですか?
std::tuple<int, double, char> message;
print(message); // the usual variadic magic
これはよく、すべての罰金とある:各クラスは自動的に各フィールドを処理することができるはずですので、自然な解決策は、必要なすべての種類のstd::tuple
をちょうど持っていることです。しかし、今では各フィールドに名前を付けたいので、コード内のフィールドを参照するときにその名前を使用できるようにしたいと思っています。単純に、またはCで、私が書かれている場合があります:
struct Message
{
int header;
double temperature;
char flag;
};
我々はタプルの再帰的なオートマジックの処理能力を失うが、私たちは文字通り、各フィールドに名前を付けることができますこの方法を。 C++では、我々は、列挙型を用いて、両方の操作を行うことができます
struct Message
{
enum FieldID { header, temperature, flag };
static const char * FieldNames[] = { "header", "temperature", "flag" };
typedef std::tuple<int, double, char> tuple_type;
template <FieldID I>
typename std::tuple_element<I, tuple_type>::type & get()
{ return std::get<I>(data); }
template <FieldID I>
static const char * name() { return FieldNames[I]; }
tuple_type data;
};
今、私は、Message m; m.get<Message::header>() = 12;
などを言うことができる、と私はフィールド上で再帰し、自分の名前が付け、自分の価値を各プリントアウトすることができます
など
今の質問: はどのように私は繰り返しなしで、効率的なコードを作成できますか?どのような方法がある外部生成ツールを必要とせずに、このような何かを達成するために、プリプロセッサ、ブーストおよびC++ 11を、組み合わせSTART_MESSAGE(Message)
ADDFIELD(int, header)
ADDFIELD(double, temperature)
ADDFIELD(char, flag)
END_MESSAGE
:
理想的には、私がこれを言うことができるようにしたいです? (私はBoost.Preprocessorがこの "水平"と "垂直"繰り返しを呼んでいると思います。フィールドデータを何とか "転置"する必要があります)。ここで重要な点は、情報を繰り返す必要がなく、 1つのフィールドには1つの変更のみが必要です。
をこの種の問題、シンプルな記述言語とカスタムプリプロセッサのインクルードファイルを生成します長期的には最高です。 「ソースファイル」は簡単に保守可能で、プロジェクトが必要とする場合は外部ツールで生成することもできます。 –
@AlexandreC .:任意の段階で、「もう少し小さなツール」は常により良い答えのように見えます。しかし、物事の壮大な計画では、あなたはあなたと一緒に持ち運び、文書化し、人々を覚えて訓練するもう一つのことがあります。箱から出てきたものを持っていることは、恐るべきマクロを設定するのに苦労することは間違いありません。 –