0

次のようなさまざまな機能を持つjson解析クラスを持つサードパーティのC++ライブラリを使用しています。

GetInt  
GetBool
GetString
GetDouble 

このクラスにアクセスできるユーティリティ関数を書きたいと思います。私はこのようなことを考えています:

class <template T>
class MyClass {
static T getValue(ThirdPartyClass someObj, const string &key) {
   if(someObj[key].IsDouble())
       return someObj[key].GetDouble();
   else if (someObj[key].IsString())
       return someObj[key].GetString();
   // ... (for other types)

} 
}

このクラスの呼び出し元は、正しい戻り値の型を保持します。

しかし、これは醜いです。if 条件を回避できる方法はありますか (マクロ置換などを使用)。サードパーティ クラスには、IsXXTypeXX および対応する GetXXTypeXX 関数 (XXTypeXX は Int、Double、String、または Bool) があります。

たとえば、次の関数を呼び出すときの戻り値の型を知っています。

int i = getValue(someObj, "intKey");
string s = getValue(someObj, "strKey");

したがって、if条件はまったく必要ありません。理想的には、私は何かを持っているように見えるので、これを行うことができます:

int i = MyClass<int>::getValue(someObj, "intKey"); 

string s = MyClass<string>::getValue(someObj, "strKey"); 
4

4 に答える 4

1

技術的には、そこで概説したパブリック インターフェイスを実現できますが、非常に見苦しいテンプレートの特殊化が必要になります。代わりにたくさんの静的関数を用意したほうがよいでしょう。テンプレートの特殊化は次のようになります。

template <typename T> class MyClass { 
    static T getValue(ThirdPartyClass someObj, const string &key) {
       // handle types that you didn't specialize for
    } 
};
template <> class MyClass <string> { 
    static string getValue(ThirdPartyClass someObj, const string &key) {
       return someObj[key].GetString();
    } 
};
template <> class MyClass <int> { 
    static int getValue(ThirdPartyClass someObj, const string &key) {
       return someObj[key].GetInt();
    } 
};
//..
于 2013-10-22T01:05:49.130 に答える
1

ソフトウェア エンジニアリングのスケルトン キー: 中間層を追加します。

#include <string>
#include <cassert>
using std::string;

class Proxy {
public:
  enum Type {
    Int,
    Bool,
    String,
    Double
  };
  Type type;
  int i;
  bool b;
  string s;
  double d;
  operator int() const {
    assert(type == Int);
    return i;
  }
  operator bool() const {
    assert(type == Bool);
    return b;
  }
  operator string() const {
    assert(type == String);
    return s;
  }
  operator double() const {
    assert(type == Double);
    return d;
  }
  Proxy(int i) : type(Int), i(i) {}
  Proxy(bool b) : type(Bool), b(b) {}
  Proxy(string s) : type(String), s(s) {}
  Proxy(double d) : type(Double), d(d) {}
}; // class Proxy

Proxy getValue(ThirdPartyClass someObj, const string &key) {
  if (someObj[key].IsDouble())
    return someObj[key].GetDouble();
  else if (someObj[key].IsString())
    return someObj[key].GetString();
   //... (for other types)
}

int main() {
  int i = getValue(someObj, "intKey"); // if type does not match, a exception will be thrown.
  string s = getValue(someObj, "strKey");
}
于 2013-10-22T01:31:52.357 に答える
1

入力を検証し、適切な型の結果を返し、その型でない場合は例外をスローする一連の静的 Get 関数 (GetInt/GetDouble...) を作成しないのはなぜですか?

于 2013-10-22T00:52:45.763 に答える
0

あなたが示したコードはコンパイルされません。double同じ関数で a 、 a string、および an を返すことはできませんint。必要なことは、戻り値の型ごとに特化してから、その型の関数のみを呼び出すことです。

template <>
class MyClass<int> getValue(ThirdPartyClass someObj, const string& key) {
    if(someOjb[key].IsInt()) return someObj[key].GetInt();
    else { /* Maybe throw an exception */ }
};

タイプごとに繰り返します。

さて、あなたはおそらく「これはばかげている。なぜ各タイプを特化しなければならないのか?」と考えているでしょう。これは、JSON ライブラリが型消去を使用しているため、実行時に型を確認する必要があるためです。作業を節約する唯一の方法は、ライブラリがテンプレート化されgetた.

必要に応じて、これらのインスタンス化を打ち消すマクロを作成できます。プリプロセッサの#(文字列化)および##(連結) 機能を利用します。それらを書き出すだけで、おそらくより明確になるでしょう。

于 2013-10-22T01:15:39.603 に答える