0

我正在使用第三方 C++ 库,它有一个 json 解析类,它具有不同的功能,如下所示:

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

为什么不写一堆静态的 Get 函数(GetInt/GetDouble...)来验证输入,返回适当的类型结果,如果不是那种类型就抛出异常?

于 2013-10-22T00:52:45.763 回答
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 回答
0

您显示的代码无法编译。您不能在同一个函数中返回 a double、 astring和 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.

如果你愿意,你可以创建一个宏来标记这些实例。它将利用预处理器的#( stringification ) 和##( concatenation ) 特性。把它们写出来可能会更清楚。

于 2013-10-22T01:15:39.603 回答