开发者

Comparing a variable to a range of values

In mathematics, the notation 18 < age < 30 denotes that age must lie between the values 18 and 30. Is it possible to use this kind of notation in the if statement? For exampl开发者_运维知识库e, I've tried executing

if(18 < age < 30)

and I get weird output, so it's not quite right. Is there a way to do this or so I simply have to write

if(age > 18) /*blah*/;
else if(age < 30) /*same blah*/;


You can do:

if (18 < age && age < 30) /*blah*/;


Nobody answered as to what exactly happened with your code, so let me pick it apart.

Consider the single statement: bool result = 18 < age < 30;

We want to evaluate the right-hand expression: 18 < age < 30

There are two operators in this expression, and since they are identical, they both have the same priority, in this case, they are thus evaluated from left to right, therefore the expression is equivalent to:

(18 < age) < 30

So let's first examine the left-hand member: 18 < age, it yields a boolean which is either true or false, typically represented as an integral value respectively 1 or 0. Thus the expression can be summed up as:

{0,1} < 30

which is always true.

Therefore, should you use assert(18 < age < 30); it would never backfire.

This implicit conversion between integral (and floating point) built-in types is really annoying...


A bit of template code can help here:

template <int min, int max> class range {
  static bool contains(int i) { return min <= i  && i < max; } // In C++, ranges usually are half-open.
};

int age = 23;
if (range<18,30>::contains(age)) { /****/ }


Is it possible to use this kind of notation in the if statement?

Yes, possible.

Desirable, hardly ever: programmers presume the behaviours described in other answers will always apply, so if you dramatically change the order of evaluation and the meaning of an expression then it will really badly confuse them and - sooner or later - cause grief. If you have a very small project with few staff, and they're basically looking to create a domain-specific language in C++, where the domain's notation is really much more readable and familiar using this notation (maybe they're mathematicians not programmers anyway), then you might in extremis consider something like I present below, though it's still likely to cause trouble.

I've implemented this kind of thing before years ago as an exploratory exercise. If you wish to do so but need help getting started: off the top of my head (i.e. doubtless buggy), consider:

struct Weird
{
    Weird(int n) : n_(n), b_is_meaningful_(false) { }
    Weird(int n, bool b) : n_(n), b_is_meaningful_(true), b_(b) { }

    int n_;

    bool b_is_meaningful_;
    bool b_;
};

Weird operator<(Weird lhs, Weird rhs)
{
    if (lhs.b_is_meaningful_)
        if (!lhs.b_) // effectively, anding with something already known false...
            return Weird(rhs.n_, false);
    return Weird(rhs.n_, lhs.n_ < rhs.n_);
}

Basically, you hack it around until you can:

Weird x = 10;
assert(6 < x < 20 < 30 < Weird(80));

At each point, the operator< creates a new Weird object with the Right Hand Side (rhs) value, while updating the boolean state on the assumption that you're effectively anding together a set of comparisons. If you really want to make a mess, you can support all kinds of things in C++, you might have a crack at say "x == 6 || 3 || 56" for fun...?


You can write a boolean expression as

((18 < age) && (age < 30))

An expression such as the above can be used whereever a boolean expression is acceptable, for example (but not limited to):

if((18 < age) && (age < 30)) { ... }

or

bool age_in_range = ((18 < age) && (age < 30));

Note that the above expression uses short-circuit evaluation of operator &&.


I know of no way to do exactly as you ask but the normal way is

Use the and operator

if (age > 18 && age <30)


Or write yourself a nice set of functions that does this

template <typename type>
bool in_range_[none|both|low|high]<type>( value, min, max )

to cater to all types of boundary included/or not

(don't use this for floating point)

In C++0x you could allow and disallow all other possibilities using the "delete" keyword that disables functions for overloads such as < float/double >

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜