开发者

How to replace macro with a template function?

开发者 https://www.devze.com 2023-01-28 11:57 出处:网络
I have the macro: #define TWO_CMD( c1, c2 ) 开发者_如何学C{ const long r1=c1; if ( r1 ) return r1; return c2; }

I have the macro:

#define TWO_CMD( c1, c2 ) 开发者_如何学C{ const long r1=c1; if ( r1 ) return r1; return c2; }

and using:

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

Func is the template member functions. But the key requirement is to keep readability of the code!

I guess there is a variant with template member function which have pointer to member functions as arguments:

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

But this syntax is not clear.


First thing first: hiding a return statement inside of a macro is Evil. When one looks at this function, it is not at all clear that those calls to TWO_CMD actually cause the function to return.

The easiest way to do this is to pass callable objects to a function template and have it return the result:

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

Used as:

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));

If your compiler and standard library do not support the C++0x or C++ TR1 bind, there is an implementation in Boost that is nearly identical.

(I've named the function Evaluate because I can't really think of a good name for this function.)


Erm, surely this is quite trivial? What's the point of over complicating? I think the code below is fairly easy to understand - why hide it?

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

Oops, had extra () from an earlier != 0 test


My answer is not directly addressing the question but just some observations:

  1. I would recommend minimising multiple return points in a function in general to keep the code flow simpler. In this case it is a simple example, but return statements at random places within a function can be missed when making changes, causing bugs.

    I tend to stick to a single return statement at the end, ie. one point of entry and one point of exit. That tends to force you into writing simpler functions with a single purpose and to move sub-operations into sub-functions.

  2. It is worth thinking outside the box when forming the structure of code. In this case, is there another simpler way to state the problem? Consider design patterns. Having to write some awkward macro or template may indicate a structural issue which could be solved by some more analysis of the problem as a whole.

  3. In your example, if a is 0 (the only value yielding false in the expression), Func<std::string>(a) is [potentially] a constant.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号