3

バイトストリームをプリミティブ型に逆シリアル化するavrチップ用の関数を書いています。できるだけ一般的な方法でそれを実行したいと思いますが、逆シリアル化するタイプを決定するためのベストプラクティスは何であるか疑問に思いました。私がこれまでに持っているアイデアには、次のものがあります。

選択肢A:

// Just write a function for each type
double deserialize_double(uint8_t *in) { }

選択肢B:

// Use a template, and pass the type in when calling
// Function:
template <typename TYPE>
TYPE deserialize(uint8_t *in) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  return u.real;
}

// Call:
double value = deserialize<double>(in);

選択肢C:

// Similar to B, but you pass in the type as a parameter
// Function:
TYPE deserialize(uint8_t *in, TYPE);

// Call:
double value = deserialize(in, double);

選択肢D:

// Use a templated class. My main issue with this is I was hoping 
// to re-use the same object for deserializing multiple types.
template <typename TYPE>
class Serializer {
  public void serialize(uint8_t *out, TYPE value) { /* code */ }
  public TYPE deserialize(uint8_t *int) { /* code */ }
};

これを行うための最良の方法に関するアイデアはありますか?おそらく私が見落としていたより簡単な方法。

4

5 に答える 5

3

手始めに、型は有効な関数の引数ではないため、CとDは無効なオプションです。今すぐそれらを除外したほうがよいでしょう。

選択肢Bは、バイトオーダーや、ユニオンをそのまま使用する場合のその他の潜在的な警告について心配していないことを前提とすると、ここでは明らかに勝者のように見えます(この作業のコンテキストが与えられるとは思えません)。

考慮すべきもう1つのことは、逆シリアル化するときにバイトストリームポインタ/インデックスを進めるためのフィードバックメカニズムがあることです。おそらくあなたは次のようなことを試すことができます

template <typename TYPE>
int deserialize(uint8_t *in, TYPE& value) {
    union {
        TYPE real;
        uint8_t base[sizeof(TYPE)];
    } u;

    for (unsigned int i = 0; i < sizeof(TYPE); i++) {
        u.base[i] = in[i];
    }
    value = u.real;
    return sizeof(TYPE);
}

// Call:
double foo, bar;
int baz;
in += deserialize(in, foo);   // Implicit double deserialize
in += deserialize(in, bar);   // Implicit double deserialize
in += deserialize(in, baz);   // Implicit int deserialize

これには、C ++テンプレートの型推論システムを利用できるという追加の利点があります(@Ashaはすでに私を打ち負かしています!)。2番目の引数は呼び出し場所で既知の型を持っているため、TYPEのテンプレート引数を明示的に指定する必要はありません。

于 2011-04-10T05:25:58.020 に答える
2

もう1つのオプションは、結果を「out」パラメーターとして返すことです。その場合、テンプレートのインスタンス化中にタイプを指定する必要はありません。このようなもの:

template <typename TYPE>
void deserialize(uint8_t *in, TYPE& out) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  out = u.real;
  return;
}

// Call:
double value = 0;
deserialize(in, value);
于 2011-04-10T05:21:40.963 に答える
1

注意の言葉:

AVRにC++を使用することは、通常、いくつかの理由で推奨されません。また、一部の機能がまったく機能しない場合もあります。特定の機能を停止する前に、ターゲットチップでコードをテストするように注意してください。道。

しかし、それはあなたが重要な機能をあきらめなければならないという意味ではありません。利用可能な言語機能に合わせてコードを調整するだけです。

于 2011-04-10T05:37:40.573 に答える
0

私の見解では、選択肢Bが最適です。読みやすさと使いやすさが向上します。さらに、TYPEはより大きなクラス/構造体になることもできますか?メソッドから値で戻っているからdeserialize()です!

于 2011-04-10T05:36:12.620 に答える
0

次の理由から、選択肢Aを使用する必要があります。

  1. 複雑さが最も少なくなります。
  2. CとC++の両方と互換性があります。
  3. タイプがサポートされていない場合に簡単な動作を提供します。

選択肢Bの構文が必要な場合は、後日、選択肢Aのコードの上にそれを実装することが常に可能であることに注意してください(さまざまなタイプに特殊化を提供することにより)。

于 2011-04-10T06:17:08.880 に答える