C ++ Пользовательская функция сравнения для list :: sort - PullRequest
3 голосов
/ 12 сентября 2009

Привет, у меня проблемы с компиляцией простого куска кода. Я создаю класс, который реализует колоду карт, и я хочу создать метод случайного использования, используя метод 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, который я не правильно использую, я не могу найти, гуглить ответ на эту проблему.

Заранее спасибо.

Ответы [ 6 ]

10 голосов
/ 12 сентября 2009

Могу я что-то сказать :) 1001 *

Во-первых, не храните указатель на 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;
7 голосов
/ 12 сентября 2009

compareRandom является функцией-членом, она имеет тип bool (Deck::*)(const Card*, const Card*), что означает, что вы не можете вызвать ее как f(a,b), то есть как sort будет вызывать ее. Вы можете сделать CompareRandom статической или автономной функцией или использовать функтор, чтобы адаптировать ее к конкретному экземпляру Deck.

6 голосов
/ 12 сентября 2009

Кстати - вы не можете перемешать, используя сортировку :) Сортировка делает некоторые предположения относительно функции сравнения.

3 голосов
/ 12 сентября 2009

Помимо того, что говорили другие: вы можете использовать std::shuffle std::random_shuffle (то, что я узнал сегодня, ура!), Я мог бы добавить, что не может использовать случайную функцию как критерий сортировки.

sort принимает строгий слабый порядок в качестве компаратора, что означает, что если a < b (или compareRandom(a,b) возвращает false, то b < a (compareRandom(b,a) возвращает true) и b == a должно возвращать false, что можно никогда не гарантируйте случайной функцией. Поведение sort в этом случае не определено. Я не знаю, заканчивается ли оно ...

2 голосов
/ 12 сентября 2009

Причина ошибки в Ответ Логана Капальдо . Теперь вы можете заменить 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() );
}
0 голосов
/ 13 сентября 2009

Я призываю вас использовать 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());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...