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++では実行できません。これを2つの別々の操作に分割する必要があります。

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

個人的には、これらの演算子のオーバーロード ソリューションはすべて、少し過剰に設計されていると思います。代わりに、2 つの単純な関数テンプレートはどうですか?

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

それを行う唯一の方法は、マーロンが提案した方法です。残念ながら、演算子のオーバーロードでこれを回避する方法はありません。演算子のオーバーロードは次のようになります。operator<=<=ここで、<=<=は三項演算子です。唯一の三項演算子は「?:」であり、これにより構文が非常に見苦しくなります。昔ながらの方法でそれを行うのが最善です。

于 2012-09-30T02:30:47.330 に答える
2

範囲ベースforのループを備えた C++11 以降、最も簡単で単純なのはRange、ループのサポートに加えて、メソッドなどのセット メンバーシップ チェックをサポートするクラス テンプレートですcontains

明らかな利点の 1 つは、このアプローチの単純なテンプレートが1 つだけで、複数の用途があることです。

そして、おそらくそれほど明白ではない利点は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 に答える
1

まず第一に、標準は、演算子のオーバーロードが引数に少なくとも 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 に答える