list :: sortのC ++カスタム比較関数
-
06-07-2019 - |
質問
こんにちは、単純なコードのコンパイルに問題があります。カードのデッキを実装するクラスを作成しています。list:: shortメソッドを使用してシャッフルメソッドを作成します。
関連コード:
deck.h
#ifndef _DECK_H
#define _DECK_H
#include <list>
#include <ostream>
#include "Card.h"
#include "RandomGenerator.h"
using namespace std;
class Deck {
private:
static const int CARD_NUMBER = Card::CARDS_PER_SUIT*Card::SUIT_NUMBER;
list<Card *> *cards;
RandomGenerator rg;
public:
Deck();
~Deck();
void shuffle();
private:
bool const compareRandom(const Card *a, const Card *b);
};
#endif /* _DECK_H */
deck.cc:
#include "Deck.h"
/**
* Fills the deck with a set of 52 cards
*/
Deck::Deck() {
cards = new list<Card *>();
for(int i = 0; i < CARD_NUMBER; i++)
cards->push_back(
new Card(
Card::Suit(int(i/Card::CARDS_PER_SUIT)),
i%Card::CARDS_PER_SUIT)
);
}
Deck::~Deck() {
gather();
for(list<Card *>::iterator c = cards->begin(); c != cards->end(); c++)
delete *c;
delete cards;
}
bool const Deck::compareRandom(const Card *a, const Card *b) {
return rg.randomBool();
}
void Deck::shuffle() {
cards->sort(compareRandom);
}
コンパイラは次のメッセージを表示します(行番号を無視します):
Deck.cc: In member function ‘void Deck::shuffle()’:
Deck.cc:66: error: no matching function for call to ‘std::list<Card*, std::allocator<Card*> >::sort(<unresolved overloaded function type>)’
/usr/include/c++/4.3/bits/list.tcc:303: note: candidates are: void std::list<_Tp, _Alloc>::sort() [with _Tp = Card*, _Alloc = std::allocator<Card*>]
/usr/include/c++/4.3/bits/list.tcc:380: note: void std::list<_Tp, _Alloc>::sort(_StrictWeakOrdering) [with _StrictWeakOrdering = const bool (Deck::*)(const Card*, const Card*), _Tp = Card*, _Alloc = std::allocator<Card*>]
問題は、私が正しく使用していないcompareRandom参照にある必要があり、この問題に対する答えをグーグルで見つけることはできません。
事前に感謝します。
解決
何か言ってもいいですか:)
最初に、Card
へのポインタを保存せず、コンテナにカードを直接保存します。何らかの理由でポインタへのポインタを保存する場合は、shared_ptr<Card>
からBoost
を使用してください。次に、シャッフル機能を実装する代わりに、std::random_shuffle
を使用してrandom-number-generator
を渡すことができます。
もう一度言います:)
これは私が念頭に置いていることです。ただし、何らかの理由でlist
を使用する必要がある場合を除き、その理由はsee
ではありません。
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
class Card
{
// ...
};
int main()
{
typedef std::vector<Card> Deck;
Deck deck;
// ... fill deck with cards.
// There is an optional third parameter,
// if you need to pass YOUR random-number-generator!
// If you do, I recommend Boost implementation.
std::random_shuffle(deck.begin(), deck.end());
}
C++
でコンテナを直接処理したいのですが、気に入らないかもしれません。また、std::vector
にパフォーマンスの問題がある場合は、typedefをstd::deque
:
typedef std::deque<Card> Deck;
他のヒント
compareRandomはメンバー関数で、bool (Deck::*)(const Card*, const Card*)
型を持っています。つまり、f(a,b)
のように呼び出すことはできません。つまり、sortが呼び出す方法です。 compareRandomを静的関数またはスタンドアロン関数にするか、ファンクターを使用してDeckの特定のインスタンスに適合させることができます。
ところで-sortを使用してシャッフルすることはできません。
他の人が言ったこととは別に: std::shuffle
std::random_shuffle
(今日学んだこと、大丈夫!)を使用できますが、ランダムに使用することはできませんできませんソート基準として機能します。
sort
は、コンパレータとして厳密な弱い順序を取ります。つまり、a < b
(またはcompareRandom(a,b)
がfalseを返す場合、b < a
(compareRandom(b,a)
はtrueを返す)およびb == a
はfalseを返す必要があります。ランダム関数で保証することはありません。この場合の<=>の動作は未定義です。
Logan Capaldoの回答のエラーの理由。次の方法でcompareRandom
をファンクターに置き換えることができます:
...
private:
struct compareRandom {
// it shouldn't give a random compare result.
// sort will not work (in Visual C++ 2008 it gives runtime assert)
bool operator()(const Card *a, const Card *b) { return rg.randomBool(); }
};
...
次に使用します
void Deck::shuffle() {
cards->sort( compareRandom() );
}
代わりにstd::random_shuffle
を使用することをお勧めします。 list
では機能しませんが、deque
またはvector
では機能するため、リストのプロパティが必要でない限り、別のコンテナを使用することをお勧めします。リストを使用する必要がある場合は、これを試してください:
void Deck::shuffle()
{
vector<Card*> temp(cards->begin(), cards->end());
random_shuffle(temp.begin(), temp.end());
cards->assign(temp.begin(), temp.end());
}