6

我希望能够写作

if (3 <= X <= 10)
{

}
else if (20 < X < 100) 
{ //...etc

在 C++ 中并让它正确评估。我知道你可以在 Python 中做到这一点,我认为这是表达条件的一种非常易读的方式。

我不想写:

if (3 <= X && X <= 10) //etc.

我怎样才能在 C++ 中做到这一点?可能吗?重载运算符会是什么样子?如果不是,你能解释为什么它不可能吗?

4

7 回答 7

11

你确定你需要这个吗?

[更新]

过了一会儿,我想到了一个看起来并不完全疯狂的想法;)

在ideone做了一个工作示例

您需要从包装第一个元素开始:

int main() {
   int x = 134, y = 14;
   if (IntComp(7) <= x <= 134)
   {
       std::cout << "Hello ";
   } 
   if (IntComp(134) > y > 12)
   {
       std::cout << "world!";
   } 
}

这里的魔力:

class IntComp {
public:
   IntComp(int x, bool result = true) : value(x), result(result) {}
   IntComp operator <= (int x) const
   {
       return IntComp(x, result && value <= x);
   }
   IntComp operator > (int x) const
   {
       return IntComp(x, result && value > x);
   }
   operator bool() const { return result; }
private:
   int value;
   bool result;
};
于 2012-09-30T02:39:26.490 回答
6

你不能在 C++ 中做到这一点。您必须将其分解为两个单独的操作:

if (3 <= X && X <= 10)
{
    ...
}
else if (20 < X && X < 100)
{
    ...
}
于 2012-09-30T02:25:54.930 回答
5

就个人而言,我认为所有这些运算符重载解决方案都有些过度设计。两个简单的函数模板怎么样?

template<typename A, typename B, typename C>
bool ordered(const A& a, const B& b, const C& c)
{
    return (a <= b) && (b <= c);
}

template<typename A, typename B, typename C>
bool between(const A& a, const B& b, const C& c)
{
    return (a < b) && (b < c);
}

void foobar(int X)
{
    if (ordered(3, X, 10))
    {

    }
    else if (between(20, X, 100))
    {
        // ...
    }
}
于 2012-09-30T12:45:54.057 回答
4

令人惊奇的是,C++ 将允许您使用用户定义的类型来做一些事情......

struct C
   {
   int value;
   bool state;
   C( int value, bool state=true ) : value(value), state(state) {}
   };

C operator <= ( int a, C b )
   {
   if ( a <= b.value ) return C(b.value,true);
   return C(b.value,false);
   }

bool operator <= ( C a, int b )
   {
   if ( a.state && a.value <= b ) return true;
   return false;
   }

std::ostream & operator << ( std::ostream & os, C c ) { os<<c.value; return os; }

void test( C X )
   {
   if (3 <= X <= 10) cerr<<"(3 <= X <= 10) is true for X="<<X<<"\n";
   }

int main()
   {
   test(2), test(3), test(4), test(10), test(11);
   }

输出...

$ ./how-to-implement-3-x-10-in-c++.cpp
(3 <= X <= 10) is true for X=3
(3 <= X <= 10) is true for X=4
(3 <= X <= 10) is true for X=10
于 2012-09-30T02:55:15.767 回答
2

由于 C++11 具有基于范围的for循环,最简单和最简单的是Range类模板,它除了支持循环外,还支持集合成员资格检查,例如作为方法contains

一个明显的优势是,这种方法只有一个简单的模板,具有多种用途。

还有一个可能不那么明显的优势是它支持const循环变量,比如……

int main()
{
    using std::wcout;  using std::endl;  using cpp::range;

    for( auto const i : range( 2, 7 ) )
    {
        wcout << i << " ";
    }
    wcout << endl;

    if( range( 2, 7 ).contains( 3 ) )
    {
        wcout << "Yes!" << endl;
    }
    else
    {
        wcout << "No!" << endl;
    }
}

像这样的定义

#include <utility>          // std::begin, std::end

namespace cpp {
    template< class Derived >
    class Comparable
    {
    public:
        friend bool operator<=( Derived const& a, Derived const& b )
        { return !(b < a); }

        friend bool operator>=( Derived const& a, Derived const& b )
        { return !(a < b); }

        friend bool operator>( Derived const& a, Derived const& b )
        { return (b < a); }

        friend bool operator!=( Derived const& a, Derived const& b )
        { return !(a == b); }
    };

    template< class TpValue >
    class Range
    {
    public:
        typedef TpValue Value;

    private:
        Value   first_;
        Value   last_;

    public:
        class Iter
            : public Comparable< Iter >
        {
        private:
            Value   current_;

        public:
            Value operator*() const { return current_; }

            void operator++() { ++current_; }

            friend bool operator<( Iter const a, Iter const b )
            { return a.current_ < b.current_; }

            friend bool operator==( Iter const a, Iter const b )
            { return a.current_ == b.current_; }

            explicit Iter( Value const v )
                : current_( v )
            {}
        };

        Value first() const { return first_; }
        Value last() const { return last_; }

        Iter begin() const { return Iter( first_ ); }
        Iter end() const { return Iter( last_ + 1 ); }

        bool contains( Value const x ) const
        { return (first_ <= x && x <= last_); }

        Range( Value const first, Value const last )
            : first_( first ), last_( last )
        {}
    };

    template< class Value >
    Range< Value > range( Value const first, Value const last )
    {
        return Range< Value >( first, last );
    }

    template< class Value >
    typename Range< Value >::Iter begin( Range< Value > const& r )
    { return r.begin(); }

    template< class Value >
    typename Range< Value >::Iter end( Range< Value > const& r )
    { return r.end(); }
}  // namespace cpp

将其概括为处理浮点范围留给读者作为练习(这里不要求)。

于 2012-09-30T14:40:05.350 回答
2

唯一的办法就是按照马龙建议的方式。不幸的是,没有办法通过运算符重载来规避这一点。重载运算符将如下所示:operator<=<=,其中 <=<= 是三元运算符。唯一的三元运算符是“?:”,这会使您的语法看起来非常难看。最好用老式的方式来做。

于 2012-09-30T02:30:47.330 回答
1

首先:标准要求运算符重载在参数中至少涉及一个用户定义的类型。因此X必须是用户定义的类型。

如果是,那么它就成为可能,没有问题。

struct Integral {
    Integral(int i): _value(i) {}
    int _value;
};

class ComparisonResult {
public:
    ComparisonResult(Integral last, bool result): _last(last), _result(result) {}

    operator bool() const { return _result; }

    Integral last() const { return _last; }

private:
    Integral _last;
    bool _result;
};

ComparisonResult operator<(Integral left, integral right) {
    return ComparisonResult(right, left._value < right._value);
}

ComparisonResult operator<(ComparisonResult cr, Integral right) {
     if (not cr) { return ComparisonResult(right, false); }
     return ComparisonResult(right, cr.last() < right);
}

// Other operators here, with the same ComparisonResult type

接着:

int main() {
    Integral X(4);
    if (3 < X < 10) { std::cout << "Hello, World!\n"; }
}
于 2012-09-30T11:47:59.580 回答