我有一些我想要优化的代码。它看起来像这样:
function abc( string format ) {
if (format == "a") { // this is a string, I shouldn't have used single quote, sorry for the confusion
classx::a t;
doit(t);
}
if (format == "b"){
classx::b t;
doit(t);
}
if (format == "c"){
classx::c t;
doit(t)
}
if (format == "d"){
classx::d t;
doit(t);
}
}
目前有许多不同类型的doit()函数
function doit( classx:a ) {
different code for a
}
function doit( classx:b ) {
different code for b
}
...等
如您所见,复制了大量代码。但是我无法弄清楚如何减少这些词。 注意 : doit(x)因不同类型而过载。 a,b,c,d类派生自名为“X”的类。
我可以创建一个指针类型classx :: X:
classx::X *t;
if (format == "a") t = new classx::a
if (format == "b") t = new classx::b
if (format == "c") t = new classx::c
if (format == "d") t = new classx::d
doit(*t)
但是仍然需要为类型classx :: X写一个doit(),带有一堆“if then”并转换为正确的类型......因为C ++无法自动检测并转换为正确的类型。
我想知道是否有更快/更聪明的方法来做到这一点。 提前谢谢。
答案 0 :(得分:3)
减少重复添加到功能映射的新条目的一种可能方法:
template<class T> void innerAbc() {
T t;
doit(t);
}
typedef std::map<std::string, void (*)()> FuncMap;
FuncMap initHandlers() {
FuncMap m;
m["a"] = &innerAbc<classx::a>;
// ... extend here
return m;
}
void abc(const std::string& format) {
static const FuncMap handlers = initHandlers();
FuncMap::const_iterator it = handlers.find(format);
if (it != handlers.end())
it->second();
}
答案 1 :(得分:1)
将格式/构造函数对放入字典中。关键是格式字符串,该值是一个指向静态工厂方法的函数指针,该方法本质上只是构造函数的一个瘦包装器。除了更容易维护之外,它还会进行哈希查找或二进制搜索,具体取决于您使用的字典/地图的类型。
答案 2 :(得分:1)
如果您在第一个else if
之后使用if
会更快,以便在找到匹配后不会继续测试。这样更紧凑,更易于阅读...
function abc(string format) {
if (format == 'a')
doit(classx::a());
else if (format == 'b')
doit(classx::b());
else if (format == 'c')
doit(classx::c())
else if (format == 'd')
doit(classx::d());
}
答案 3 :(得分:1)
一个简单的模板方法摆脱了大量重复的代码。如果你想避免使用一系列'if'语句,你可以使用map或带二进制搜索的有序向量。
template<typename T> void forward_doit()
{
T t;
doit(t);
}
void func(string const& s)
{
if (s == "a") return forward_doit<Classx::a>();
if (s == "b") return forward_doit<Classx::b>();
if (s == "c") return forward_doit<Classx::c>();
// ...
}
答案 4 :(得分:0)
这是一种使用宏的方法,假设格式实际上是一个字符串。您在原始(Javascript?)代码中使用的单引号是用于字符。
我无法使用模板进行远程操作,是的,有时宏仍然有用!
#define FORMATTER(ltr) \
if (format == #ltr) { \
classx::##ltr t; \
doit(t); \
}
#define ELSEFORMATTER(ltr) else FORMATTER(ltr)
void abc( std::string format ) {
FORMATTER(a)
ELSEFORMATTER(b)
ELSEFORMATTER(c)
ELSEFORMATTER(d)
}
答案 5 :(得分:0)
使用boost预处理器
#define MACRO(r, data, elem) \
if (format == '(elem)') doit(classx::(elem)()); \
else
BOOST_PP_SEQ_FOR_EACH(MACRO, _, (a)(b)...) {
... // else condition
}
我不知道如何将宏放在''
内:How to single-quote an argument in a macro?