开发者

More concise way to write the following statement

开发者 https://www.devze.com 2023-01-08 15:37 出处:网络
Is there a more concise way to write the following C++ statements: 开发者_运维技巧 int max = 0; int u = up();

Is there a more concise way to write the following C++ statements:

开发者_运维技巧
int max = 0;

int u = up();
if(u > max)
{
 max = u;
}

int d = down();
if(d > max)
{
max = d;
}

int r = right();
max = r > max ? r : max;  

Specifically is there a way to embed the assignment of the functions return inside the if statement/ternary operator?


Assuming that:

  • The idea was to remove the local variables (i.e. you don't need u, d, r later on)
  • Evaluation order doesn't matter

... then you can just use std::max:

int m = max(max(max(0, up()), down()), right());

If this is the return value of the function:

return max(max(max(0, up()), down()), right());

Note that that can evaluate the functions in any order, rather than the string up, down, right order in your original code.


#include <algorithm>
using namespace std;
...

int maxn = max(max(up(), down()), right());

If I'm not mistaken.


You can embed assignments, but not variable declarations within the if statements:

int max = 0, u, d, r;

if ((u = up()) > max)
  max = u;

if ((d = down()) > max)
  max = d

max = (r = right) > max ? r : max;


int u = up(), d = down(), r = right();
int max = (u > d) ? u : d;
max = (max > r) ? max : r;

Specifically is there a way to embed the assignment of the functions return inside the if statement/ternary operator?

IMO That would produce terrible legibility


max = std::max(right(), max);


I'd write something like this:

int max = 0;

maximize(max, up());
maximize(max, down());
maximize(max, right());

Where maximize takes the first variable by reference, and a second variable as an offering. If the offering is greater than the first variable, then the first variable is set to the offering.

void maximize(int& v, int offering) {
   if (offering > v) {
      v = offering;
   }
   // or use std::max
}

Benefits

The other alternative to maximize is this one-liner nested-max expression:

// nested-max alternative; more "functional" style
int v = max(max(max(defaultValue, val1), val2), val3);

Contrast this with the multi-step refinement maximization process:

// multi-step maximize alternative; more "imperative" style
int v = defaultValue;
maximize(v, val1);
maximize(v, val2);
// perhaps do something else in between...
maximize(v, val3);

Though not as concise, this latter approach offers the following:

  • A linearized form can be more readable than a deeply nested max expression
  • You can do something in between each maximization steps if you need to
  • The order of the maximization steps are explicit
    • It's also easily to reorder by moving individual statements around

On assignment in condition

And now we address the following part of the question:

Specifically is there a way to embed the assignment of the functions return inside the if statement/ternary operator?

If you insist on doing something like this, you can always use a temporary variable as follows:

int offer;

if ((offer=up()) > max) {
  max = offer;
}
if ((offer=down()) > max) {
  max = offer;
}

max = ((offer=right()) > max) ? offer : max;

This does not result in a very readable code in this case, but there are idiomatic ways to use an assignment in a condition in some scenarios.

Related questions

  • Why would you use an assignment in a condition?


I would like to point out that if the execution order of up,down and right is not important, then this sequence should be used:

max(max(0,up()), max(down(),right())

because it minimizes result dependencies and should execute faster on common super scalar CPUs.


The more generic problem is finding the max of the given inputs. We can generalise std::max to something like this:

template <typename T, typename ... Ts>
T Max (const T && input_1, const Ts && ... inputs)
{
    // initialise:
    T max = input_1;

    // find max:
    ([&] (T i)
    {
        if (i > max)
            max = i;

    } (inputs), ...);
    
    return max;
}

(above is c++17 style, but we can write the same thing in a less pretty way in earlier c++)

This makes finding the max like so:

int max = Max<int>(0, up(), down(), right());

We add the <int> to specify what we want to convert the inputs to, in case some are unsigned, float, etc.

If the order of calls actually does matter, then there's not much better we can do than this:

int max = 0;
max = std::max(max, up());
max = std::max(max, down());
max = std::max(max, right());

We could make a generic function, like Max above, that takes in a list of functions/functors instead, but it's such an unusual issue that I doubt you'd re-use the code.

0

精彩评论

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