如何用模板函数替换宏?

时间:2010-12-03 06:48:02

标签: c++ templates macros

我有宏:

#define TWO_CMD( c1, c2 ) { const long r1=c1; if ( r1 ) return r1; return c2; }

并使用:

long MyClass::SomeFunc( long a )
{
    //...
    if ( a )
        TWO_CMD( Func<int>(a), Func<void>() );
    else
        TWO_CMD( Func<double>(), Func<std::string>(a) );
    //...
}

Func是模板成员函数。 但关键要求是保持代码的可读性!

我想有一个带模板成员函数的变体,它有指向成员函数的指针作为参数:

return two_cmd( Func<int>, a, Func<void> );

但这种语法不明确。

3 个答案:

答案 0 :(得分:4)

首先要做的是:在宏中隐藏一个return语句是邪恶的。当人们查看这个函数时,对TWO_CMD的调用实际上导致该函数返回并不清楚。

最简单的方法是将可调用对象传递给函数模板并让它返回结果:

template <typename R, typename F, typename G>
R Evaluate(const F& f, const G& g) {
    R x = f();
    return x ? x : g();
}

用作:

return Evaluate<long>(
    std::bind(&MyClass::Func<int>, this, a), 
    std::bind(&MyClass::Func<void>, this));

return Evaluate<long>(
    std::bind(&MyClass::Func<double>, this), 
    std::bind(&MyClass::Func<std::string>, this, a));

如果您的编译器和标准库不支持C ++ 0x或C ++ TR1 bind,那么Boost中的实现几乎完全相同。

(我已将函数命名为Evaluate,因为我无法真正想到这个函数的好名字。)

答案 1 :(得分:2)

嗯,嗯,这肯定是微不足道的?过分复杂的重点是什么?我认为下面的代码很容易理解 - 为什么隐藏它?

long res = 0;
if ( a )
    return (res = Func<int>(a)) ? res : Func<void>();
else
    return (res = Func<double>()) ? res : Func<std::string>(a);

哎呀,从之前的()测试中得到额外的!= 0

答案 2 :(得分:0)

我的回答并非直接解决问题,只是一些观察:

  1. 我建议最小化函数中的多个返回点以保持代码流更简单。在这种情况下,它是一个简单的例子,但是在进行更改时可能会错过函数中随机位置的返回语句,从而导致错误。

    我倾向于坚持最后的一个回复声明,即。一个入口点和一个出口点。这往往会迫使您只为一个目的编写更简单的函数,并将子操作移动到子函数中。

  2. 在形成代码结构时,在框外思考是值得的。在这种情况下,是否有另一种更简单的方式来陈述问题?考虑设计模式。必须编写一些尴尬的宏或模板可能表明结构性问题可以通过对整个问题的更多分析来解决。

  3. 在您的示例中,如果a为0(表达式中唯一的值为false),则Func<std::string>(a) [可能]为常量。