rmaicle

Programming is an endless loop; it's either you break or exit.

Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License (CC BY-SA).
You are free to copy, reproduce, distribute, display, and make adaptations but you must provide proper attribution. Visit https://creativecommons.org/ or send an email to info@creativecommons.org for more information about the License.

return_if Construct

Date: 2015-12-16 11:41:22 +0000

The idea is to tell the reader up front that the code will exit the function if some condition evaluates to true. This does not intend to replace the if-return statement. I admit, this is merely aesthetics or syntatic sugar. There is no other benefit from using the built-in if statement. But somehow I find return_if clearer and kind of support the flow of thought.

A Simple Use Case

The following psuedocode, demonstrates a use case for return_if construct. If a certain condition evaluates to true, it returns the return_value.

1
2
3
4
5
6
7
int compute() {                         int compute() {
    if (condition) {                        return_if (condition, <return_value>);
        return <return_value>;
    }
    ...                                     ...
    return 0;                               return 0;
}                                       }

An implementation would be the following. Yes, it uses the preprocessor again as with my other devious schemes.

1
2
3
4
5
6
#define RETURN_IF(C, R)             \
    do {                            \
        if (!!(C)) {                \
            return R;               \
        }                           \
    } while ((void)0, 0)

Here is a simple actual code using the simple construct.

1
2
3
4
bool is_odd(int n) {
    RETURN_IF (n % 2, true);
    return false;
}
Executing a Block of Code

Now, what if the condition needs to execute a block of code before returning.

1
2
3
4
5
6
7
8
int compute() {                         int compute() {
    if (condition) {                        return_if (condition, <return_value>) {
        ...                                     ...
        return <return_value>;              }
    }
    ...                                     ...
    return 0;                               return 0;
}                                       }

A simple implementation would be the following code. Note that there is an extra end_ri macro wherein the actual return statement is executed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <typename T>
struct ReturnValue {
    ReturnValue(T t) : value(t) { }
    T value;
};

#define return_if(C, R)                                 \
    if (!!(C)) {                                        \
        namespace nuri = ::negerns::util::returnif;     \
        auto rv = nuri::ReturnValue<decltype(R)>(R);    \
        [=]

#define end_ri                                          \
        ();                                             \
        return rv.value;                                \
    }

Using the psuedocode above, here is a simple use case in actual C++ code. The left hand code using the if statement. The right hand code using the return_if construct.

1
2
3
4
5
6
7
8
int is_odd(int n) {                         int is_odd(int n) {
    if (n % 2) {                                RETURN_IF (n % 2, true) {
        std::cout << n << "is odd.\n";              std::cout << n << "is odd.\n";
        return true;                            }
    }
    std::cout << n << "is even.\n";             std::cout << n << "is even.\n";
    return false;                               return false;
}                                           }
Afterthoughts

After looking at the code, there doesn’t seem to be much to gain from a return_if construct. Except maybe from it’s kind of easier to grasp the intent of the code.

It is interesting to see that other language statements are declarative. They declare their intention; like for which tells the reader that it is going to iterate. The if statement, or it’s cousin the switch statement, isn’t declarative. I find it like a pause when reading code.

When reading an if statement, it doesn’t say whether the if statement will return from a function or not until you come reading to the line with a return statement. This if statement use case forces me to read ahead and move back from where I left off. When I see a return_if construct, I know right away without scrolling my eyes down the code that it will return from the function.

Function Return Type Deduction using decltype(auto)

There is also something to consider when using a return_if construct in a function whose return type is declared decltype(auto). Here is Scott Meyers’ blog about C++14 decltype(auto). This is a topic on its own but I would like to mention it here since the construct above deals with return statements. A function return type declared as decltype(auto) will return a reference when the return value is wrapped within parenthesis.

  •  thoughts