2012-03-05 9 views
1

ポインタの配列のオブジェクトがメンバ関数に与えられたパラメータと同じ名前(メンバ変数)を持つ回数を数える必要があります。私はさまざまなアプローチを試みましたが、どれも働いていませんでした。私のコードはコンパイルされません。エラーは次のとおりです。「エラーC2514: 'MyComparator':クラスにコンストラクタがありません」ここでは、concurenciesのカウントに使用される比較と関数に使用するクラスのコードを示します。オブジェクトのポインタのベクトルにSTLアルゴリズムを使用する(C++)

//definition of the vector 
vector<Class1*> files; 
... 
int Class2::countNames(string name) 
    { 
     return count_if(files.begin(), files.end(), bind2nd(MyComparator(),name)); 
    } 
... 
class MyComparator{ 
public: 
bool operator()(const CFileType*& ob1, const string &str) 
{ 
    return ob1->getName()==str; 
} 
}; 

私は時間のためにこれで苦労していると私は、STLを使用して、それをしたいです。ここでのキャッチは、私はポインタのベクトルを持っている、私はそれがパラメータを与える必要があり、私はbind2nd()が正しい方法だと思う、述語関数を必要としない法線ベクトルを持っていた場合。どんな助けでも大歓迎です!

答えて

1

C++ 11では、ラムダ式を使用することができました。古くなっているbind2ndよりはるかに簡単です。

#include <string> 
#include <vector> 
#include <algorithm> 
#include <iostream> 

class Class1 { 
public: 
    Class1(const std::string& name) : Name(name) { 
    } 
    const std::string& getName() const { 
     return Name; 
    } 
private: 
    std::string Name; 
}; 

size_t CountMatchingNames(const std::vector<Class1*>& v, const std::string& name) { 
    return std::count_if(
     v.begin(), 
     v.end(), 
     [&name](Class1* c1) { return name == c1->getName(); } 
    ); 
} 

int main() { 

    Class1 rob("rob"); 
    Class1 bob("bob"); 
    Class1 mitch("mitch"); 

    std::vector<Class1*> v; 
    v.push_back(&bob); 
    v.push_back(&mitch); 
    v.push_back(&rob); 
    v.push_back(&mitch); 
    v.push_back(&bob); 
    v.push_back(&bob); 

    std::cout << "rob count:\t" << CountMatchingNames(v, "rob") << std::endl; 
    std::cout << "bob count:\t" << CountMatchingNames(v, "bob") << std::endl; 
    std::cout << "mitch count:\t" << CountMatchingNames(v, "mitch") << std::endl; 

    return EXIT_SUCCESS; 

} 

この版画:たとえば

まず第一には、あなたがそれを使用するときに、あなたの比較クラスが知られていることを確認する必要があり
rob count:  1 
bob count:  3 
mitch count: 2 
+0

ありがとうございます、それは完璧に動作し、** bold ** bind2nd()** bold ** – Goshutu

+0

@Goshutuを使用するよりはるかにコンパクトです参照してベクトルを渡すのを忘れました(編集を参照してください) 。これは正確さには影響しませんが、 'CountMatchingNames'への呼び出しごとにベクトルをコピーする必要がなくなるため、パフォーマンスに影響します。 –

+0

これはクラス – Goshutu

1

:の定義の前でMyComparatorの定義を移動countNames()が私の最初のステップになります。つまり、bind2nd()は、あなたが提供しているものより少し上手く扱っている関数オブジェクトを知りたいと考えています。それは一般的にresult_typefirst_argument_type、およびsecond_argument_typeを知りたいと思っています。これらはstd::binary_function<bool, CFileType const*, std::string const&>から取得することも、明示的に定義することもできます。私はそれが必要とは思わないが、関数呼び出しオペレータconstを作成したいかもしれない。一方、関数ではなく関数オブジェクトを定義している場合(typedefstd::ptr_fun()を使用して得ることができます)、個人的には名前が何となく魅力的なものになると思っています。楽しいあなたがそれらを)使用しなければならないとき、あなただけの最初の場所でバインダーと干渉する全体の道を行くとすることはできません。

class MyComparator { 
public: 
    MyComparator(std::string const& value): value_(value) {} 
    bool operator()(CFileType const* obj) const { 
     return obj->getName() == this->value_; 
    } 
private: 
    std::string value_; 
}; 
... 
std::count_if(files.begin(), files.end(), MyComparator(name)); 

関数を定義し、それを結合するときには、バインダーを使用して、ほぼ同じ効果を得ることができます。 Typeically、私はコードを試していないとき、私はそれが間違って取得するが、それはこのようなものになります:あなたが参照ではなく、それをすべての時間をコピーすることによってname引数を渡したいと感じた場合

bool myComparator(CFileType const* obj, std::string name) { 
    return obj->getName() == name; 
} 
... 
std::count_if(files.begin(), files.end(), 
       std::bind2nd(std::ptr_fun(myComparator), name)); 

を、 std::bind2nd()を使用することはできません。少なくとも、C++ 2011コンパイラを使用しない限り、それはコンパイラが好きではない連続するconstのキーワードを持つ型を作成します。たとえば、

std::count_if(files.begin(), files.end(), boost::bind(myComparator, _1, name)); 

...とstd::string const& nameすべきnameパラメータの宣言を変更:この問題はありませんboost::bind()

1

あなたはここではいくつかの問題を抱えて:あなたはそれを使用した後MyComparatorを定義しているように見えます

  • を。タイプは使用前に定義する必要があります。
  • ベクトルにはClass1*が含まれていますが、コンパレータはCFileType*で動作します。
  • 廃止予定のbind1stbind2ndは使いにくく、関数タイプでさまざまなタイプを定義する必要があります。新しいstd::bind(またはboost::bind)を使用することはできませんと仮定すると、これを修正する最も簡単な方法は、const宣言するstd::binary_function<Class1*, string, bool>
  • からoperator()ニーズを継承するMyComparatorためです。

あなたのコンパイラがC++ 11をサポートしている場合は、あなたがstd::bindまたはλのいずれかを使用して、より簡単に、これを書くことができます:原則として

count_if(files.begin(), files.end(), bind(MyComparator(), placeholders::_1, name)); 

または

count_if(files.begin(), files.end(), [&name](Class1 const * p){return p->getName()==name;}); 
1

あなたのアイデアの作品、しかし、

  1. 比較クラスは使用前に定義する必要があります。
  2. binary_functionから継承して、必要なtypedefを含める必要があります。
  3. operator()constと宣言する必要があります。これらの補正で

は、次の例では、私の作品:

#include <vector> 
#include <functional> 
#include <string> 
#include <algorithm> 
#include <iostream> 

using namespace std; 

struct Class1 { 
    string getName() const { return "aaa"; } 
}; 

//... 
class MyComparator: public binary_function<const Class1*, string, bool> { 
public: 
bool operator()(const Class1* ob1, const string &str) const 
{ 
    return ob1->getName()==str; 
} 
}; 

vector<Class1*> files; 
//... 
int countNames(string name) 
    { 
     return count_if(files.begin(), files.end(), bind2nd(MyComparator(),name)); 
    } 

int main() { 
    files.push_back(new Class1); 
    files.push_back(new Class1); 
    cout << countNames("aaa") << ' ' << countNames("bbb") << endl; 
} 

注意をしかし、ポインタのベクトルを持つことが簡単に(私の例のように)メモリリークにつながること。 Boost.PointerContainerまたは(C++ 11の場合)unique_ptrのコンテナを使用することを検討してください。

+0

のメンバー関数であるため、問題はありません。このメソッドを既に試してみましたが、同じエラーメッセージが表示されましたが、「Branko Dimitrijevic」の答えが働いてプログラムが実行されました今は大丈夫です! – Goshutu

関連する問題