模板替换函数名称

时间:2013-10-22 00:37:00

标签: c++

我正在使用第三方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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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();
    } 
};
//..

答案 2 :(得分: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");
}

答案 3 :(得分:0)

您展示的代码无法编译。您不能在同一函数中返回doublestringint。你需要做什么专门针对每种返回类型,然后只调用该类型的函数:

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)功能。将它们写出来可能会更清楚。