Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何用模板函数替换宏?_C++_Templates_Macros - Fatal编程技术网

C++ 如何用模板函数替换宏?

C++ 如何用模板函数替换宏?,c++,templates,macros,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&g

我有宏:

#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) );
    //...
}

但这种语法并不清楚。

首先,在宏中隐藏return语句是有害的。查看此函数时,根本不清楚对
TWO\u CMD
的调用是否会导致函数返回

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

template <typename R, typename F, typename G>
R Evaluate(const F& f, const G& g) {
    R x = f();
    return x ? x : g();
}
模板
R评估(恒F&F、恒G&G){
rx=f();
返回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));
返回值(
std::bind(&MyClass::Func,this,a),
std::bind(&MyClass::Func,this));
回报评估(
std::bind(&MyClass::Func,this),
std::bind(&MyClass::Func,this,a));
如果编译器和标准库不支持C++ 0x或C++ Tr1<代码> BIN < /C>,在Boost中有一个几乎相同的实现。
(我将函数命名为
Evaluate
,因为我真的想不出这个函数的好名字。)

呃,这肯定很简单吧?过分复杂化有什么意义?我认为下面的代码相当容易理解-为什么要隐藏它

long res = 0;
if ( a )
    return (res = Func<int>(a)) ? res : Func<void>();
else
    return (res = Func<double>()) ? res : Func<std::string>(a);
long res=0;
如果(a)
返回(res=Func(a))?res:Func();
其他的
返回(res=Func())?决议:Func(a);

哎呀,从以前的
!=0
测试

我的回答不是直接针对问题,而是一些观察结果:

  • 我建议将函数中的多个返回点最小化,以使代码流更简单。在本例中,这是一个简单的示例,但在进行更改时,函数中随机位置的返回语句可能会丢失,从而导致错误

    我倾向于在结尾只使用一个返回语句,即一个入口点和一个出口点。这往往会迫使您编写具有单一用途的更简单函数,并将子操作移动到子函数中

  • 在形成代码结构时,有必要跳出框框进行思考。在这种情况下,是否有其他更简单的方法来说明问题?考虑设计模式。必须编写一些笨拙的宏或模板可能表明存在结构性问题,可以通过对问题进行更多的整体分析来解决

  • 在您的示例中,如果a是0(表达式中唯一产生false的值),
    Func(a)
    是一个常量


  • 不幸的是,这个版本很难阅读(用Band,和这个,等等)。@ SimulyTotoAsAsQue:类似C++的其他部分,一旦你使用了它,这个语法就相当简单了。是的,这需要一些时间来适应,但是这里使用的工具是非常宝贵的。如果
    Func
    是一个成员函数,那么它应该是
    std::bind(&MyClass::Func,this,a)
    等等?@简单地问:当然,它比猜测一个宏将退出函数并返回更容易阅读。请注意,即使您知道宏的作用,也会在
    if-else
    块后添加
    /…
    ,即使无法访问该
    /…
    。@visitor。哎呀。固定的。谢谢。保持代码的可读性!!!它现在不可读。除了神秘的附加括号,这是更可读的版本。我有太多的TWO_CMD调用,您的示例建议使用更多的代码符号。而且函数(或宏)更灵活。例如,在一个地方,我可以在两个调用之间添加一些操作(例如sleep)。我没有意识到你在寻找code golf!这个宏是否混合了不同的功能和不同的效果?那更邪恶。。。
    long res = 0;
    if ( a )
        return (res = Func<int>(a)) ? res : Func<void>();
    else
        return (res = Func<double>()) ? res : Func<std::string>(a);