0

クラスを含むベクターで std::less を使用する方法、すべての Google の結果はプレーンな int の例です。

クラスに関しては、例えば:

class A{
   public:
      A( int value = 0 ):m_value(value){};
      int m_value;
};

次のようなことをする方法:

std::count_if( m_cells.begin(), m_cells.end(), std::less< int >() );

Less は int ではなく A を受け取ります。std::less< A >

ファンクターがあまり必要ないようoperator()()ですが、これを回避するにはどうすればよいですか? operator<( int a ) を実装する必要がありますか? バインドしますか?ほかに何か?

コード:

  1 #include <iostream>
  2 #include <vector>
  3 #include <algorithm>
  4
  5 using namespace std;
  6
  7 class A
  8 {
  9    public:
 10       A(int a = 0 ):m_value(a) {}
 11       bool operator!=( int a )
 12       {
 13          return m_value != a;
 14       }
 15
 16       bool operator<( A &a )
 17       {
 18          return m_value < a.m_value;
 19       }
 20
 21       int m_value;
 22 };
 23
 24
 25 int main(){
 26    std::vector< A > m_cells( 5 );
 27
 28    m_cells[2].m_value = 3;
 29    m_cells[3].m_value = 4;
 30    m_cells[4].m_value = 4;
 31    std::count_if( m_cells.begin(), m_cells.end(), std::less< A >() );
 32    return 0;
 33 }
 34

これにより、次の結果が得られます。

/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_algo.h:4437: error: no match for call to ‘(std::less<A>) (A&)’
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_function.h:229: note: candidates are: bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]
4

3 に答える 3

2

operator<問題は、内部での使用の定義にありますstd::less<>

現在のoperator<では、演算子がそのオペランドのいずれかを変更する可能性があることをコンパイラに効果的に伝えています (演算子もその引数も宣言されていないためconst)。std::less<>のオペランドを変更したくないため、operator<実装は受け入れられません。

これを修正するには、 の定義を次のように変更しますoperator<

16       bool operator<( const A &a ) const
17       {
18          return m_value < a.m_value;
19       }

const( 16 行目の追加に注意してください)。operator<これは、オペランドのいずれも変更しないことをコンパイラに伝え、で使用できるようにしstd::less<>ます。

于 2012-11-23T13:56:14.047 に答える
2

std::lessのベクトルだったとしても、それ以上のものが必要ですintstd::count_if単一の引数で述語を呼び出します。std::less 2つ必要です。

他にも多数の機能オブジェクトがあり、 std::bind2ndそれらを組み合わせることができます。ただし、正しい組み合わせを見つけるのは簡単ではなく、結果は判読不能で壊れやすいため、お勧めする解決策ではありません。C++11 を使用している場合は、lamba があります。これは明らかに最適な方法です。それ以外の場合、boost::bind は非常に便利です。Boost を使用できない場合、唯一の合理的な解決策は、次のような独自の述語オブジェクトを作成することです。

class ALessThan
{
    int myUpperLimit;
public:
    ALessThan( int upperLimit ) : myUpperLimit( upperLimit ) {}
    bool operator()( A const& object ) const
    {
        return object.m_value < myUpperLimit;
    }
};

(どのように実行しても、述語に引数を提供する必要があることに注意してください。何未満ですか?)

于 2012-11-23T13:36:43.143 に答える
2

operator<for を実装してから、他のオプションAを渡しstd::less<A>ます (たとえば、変換演算子をint-YUCKYUCKYUCKYUCK に実装できます)。

編集:続行するには...

James が言うように、std::less<>2 つの引数が必要です。c++03 に固執している (そしてブーストがない) 場合は、次のようなことができます。

std::count_if( m_cells.begin(), m_cells.end() ,std::bind1st(std::less<A>(), 3) )

基本的に、引数の 1 つがバインドされます- これは最初の引数 (左側を考慮してください) であり、述語をどのように機能させたいかによって3、2 番目の引数 (右側 - を使用) にバインドすることもできます。std::bind2nd

operator<このアプローチでは、適切に実装する必要があります。

bool operator<(A const& a) const
{
}

EDIT2: c++11 の場合、次のいずれかを試すことができます。

 std::cout << std::count_if( m_cells.begin(), m_cells.end() , [](A const& a) { return 3 < a.m_value; } ) << std::endl; // lambda
 std::cout << std::count_if( m_cells.begin(), m_cells.end() , std::bind(std::less<A>(), _1, 4) ) << std::endl; // bind second argument (rhs)
 std::cout << std::count_if( m_cells.begin(), m_cells.end() , std::bind(std::less<A>(), 3, _1) ) << std::endl; // bind first argument (lhs)
于 2012-11-23T13:25:14.670 に答える