2

I have the macro:

#define TWO_CMD( c1, c2 ) { 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.

1
  • 1
    Keep the readability of the code!!! Its not readable now. Commented Dec 3, 2010 at 7:49

3 Answers 3

4

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

Sign up to request clarification or add additional context in comments.

4 Comments

This version is hard to read unfortunately (with bind, &, this, etc).
@simply_to_ask: Like the rest of C++, this syntax is quite straightforward once you have used it for a while. Yes, it takes some getting used to, but the tools used here are invaluable.
If Func is a member function, then it should be std::bind(&MyClass::Func<int>, this, a) etc?
@simply_to_ask: for sure it is simpler to read than having to guess that a macro will bail out of your function with a return. Note that even you, knowing what the macro does, added // ... after the if-else blocks, even if that // ... can never be reached.
2

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

3 Comments

Mysterious extra parentheses aside, this is the more readable version.
I have too much calls of TWO_CMD and your example suggest more code symbols. And the function (or macro) is more flexible. For example in one place i can add some operation between two calls (sleep for example).
I didn't realize that you were after code golf! Are you mixing different functions with different effects with this macro? That's even more evil...
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.