make_heap или ?
От: 13akaEagle Россия  
Дата: 26.12.06 14:04
Оценка:
struct Team 
{
    std::string _name;

    Team::Team(std::string name);
};

struct Game
{
    Team& _first;
    Team& _second;
    Score score;
//    TDateTime _datetime;
    std::string _datetime;

    Game(Team& first, Team& second, std::string datetime);
    Game& operator=(const Game& game);
    friend bool operator>(const Game& left, const Game& rigth);
};

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<Game> g;

    Team a("Russia");
    Team b("Litva");
    Team c("Estonia");

    g.push_back(Game(a, b, "25.12.2006"));
    g.push_back(Game(c, b, "26.12.2006"));
    g.push_back(Game(a, c, "27.12.2006"));


    make_heap(g.begin(), g.end(), std::greater<Game>());
    for (std::vector<Game>::iterator it = g.begin(); it != g.end(); ++it)
    {
        Game& game = static_cast<Game>(*it);
        std::cout << game._first._name << " " << game._second._name << std::endl;
    }
}


Выводит:

Estonia Litva
Estonia Litva
Estonia Estonia

Совсем не то, что ожидалось.
Как будет правильно?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: make_heap или ?
От: Аноним  
Дата: 27.12.06 09:36
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

[]

Лажа в Game::operator= (текст которого не приведен).
Re[2]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 11:35
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, 13akaEagle, Вы писали:


А>[]


А>Лажа в Game::operator= (текст которого не приведен).


Game& Game::operator=( const Game& game )
{
    _first = game._first;
    _second = game._second;
    _datetime = game._datetime;
    return *this;
}

Где именно?

ЗЫ: Конструкторы и операторы достаточно тривильаны, потому и не приводил их.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: make_heap или ?
От: Кодёнок  
Дата: 27.12.06 12:26
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

Значит, лажа в копирующем конструкторе.
Re[4]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 14:12
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Здравствуйте, 13akaEagle, Вы писали:


Кё>Значит, лажа в копирующем конструкторе.


Game::Game( const Game& game ) : _first(game._first), _second(game._second), _datetime(game._datetime)
{}

Проблемы не решает, результат тот же.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: make_heap или ?
От: Ubivetz Украина  
Дата: 27.12.06 14:54
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

E>
E>struct Team 
E>{
E>    std::string _name;

E>    Team::Team(std::string name);
E>};

E>struct Game
E>{
E>    Team& _first;
E>    Team& _second;
E>    Score score;
E>//    TDateTime _datetime;
E>    std::string _datetime;

E>    Game(Team& first, Team& second, std::string datetime);
E>    Game& operator=(const Game& game);
E>    friend bool operator>(const Game& left, const Game& rigth);
E>};
E>

Реализацию friend bool operator>(const Game& left, const Game& rigth); в студию.
Скорее всего там бочина.
Эх, люблю выпить и переспать с кем нибудь!
Но чаще выходит перепить с кем — нибудь и выспаться...
Re[2]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 14:57
Оценка:
Здравствуйте, Ubivetz, Вы писали:

U>Реализацию friend bool operator>(const Game& left, const Game& rigth); в студию.

U>Скорее всего там бочина.

bool operator>(const Game& left, const Game& rigth)
{
    return left._datetime > rigth._datetime;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: make_heap или ?
От: Ubivetz Украина  
Дата: 27.12.06 15:07
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

E>Здравствуйте, Ubivetz, Вы писали:


U>>Реализацию friend bool operator>(const Game& left, const Game& rigth); в студию.

U>>Скорее всего там бочина.

E>
E>bool operator>(const Game& left, const Game& rigth)
E>{
E>    return left._datetime > rigth._datetime;
E>}
E>

Не пойму ещё, как оно может выводить

Estonia Litva
Estonia Litva
Estonia Estonia

???
Может ты что-то путаешь?
Эх, люблю выпить и переспать с кем нибудь!
Но чаще выходит перепить с кем — нибудь и выспаться...
Re[4]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 15:18
Оценка:
Здравствуйте, Ubivetz, Вы писали:

U>Не пойму ещё, как оно может выводить

U>

U>Estonia Litva
U>Estonia Litva
U>Estonia Estonia

U>???
U>Может ты что-то путаешь?

Да вроде ничего не путаю.
Понять ничего не могу, но мне кажется, что make_heap что-то делает неправильно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: make_heap или ?
От: Ubivetz Украина  
Дата: 27.12.06 15:20
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

E>Здравствуйте, Ubivetz, Вы писали:


U>>Не пойму ещё, как оно может выводить

U>>

U>>Estonia Litva
U>>Estonia Litva
U>>Estonia Estonia

U>>???
U>>Может ты что-то путаешь?

E>Да вроде ничего не путаю.

E>Понять ничего не могу, но мне кажется, что make_heap что-то делает неправильно.
Когда ты ему указываешь std:greater<Game>(), ты этим самым сортируешь коллекцию.
Почему у тебя появилась пара Estonia Estonia?
Эх, люблю выпить и переспать с кем нибудь!
Но чаще выходит перепить с кем — нибудь и выспаться...
Re[6]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 15:32
Оценка:
Здравствуйте, Ubivetz, Вы писали:

U>Когда ты ему указываешь std:greater<Game>(), ты этим самым сортируешь коллекцию.

U>Почему у тебя появилась пара Estonia Estonia?
Вот ради этого я и решил попросить совета в форуме.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: make_heap или ?
От: a-lex Россия  
Дата: 27.12.06 16:07
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

E>Где именно?


struct Game
{
    Team& _first;    // ссылка
    Team& _second;   // ссылка
    Score score;
//    TDateTime _datetime;
    std::string _datetime;

    Game(Team& first, Team& second, std::string datetime);
    Game& operator=(const Game& game);
    friend bool operator>(const Game& left, const Game& rigth);
};

Game& Game::operator=( const Game& game )
{
    _first = game._first;       // присваивание через ссылку
    _second = game._second;     // присваивание через ссылку
    _datetime = game._datetime;
    return *this;
}


int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<Game> g;

    Team a("Russia");
    Team b("Litva");
    Team c("Estonia");

    g.push_back(Game(a, b, "25.12.2006"));
    g.push_back(Game(c, b, "26.12.2006"));   // теперь a == c
    g.push_back(Game(a, c, "27.12.2006"));   // теперь b == c


    make_heap(g.begin(), g.end(), std::greater<Game>());
    for (std::vector<Game>::iterator it = g.begin(); it != g.end(); ++it)
    {
        Game& game = static_cast<Game>(*it);
        std::cout << game._first._name << " " << game._second._name << std::endl;
    }
}
Re[4]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 16:13
Оценка:
Здравствуйте, a-lex, Вы писали:

AL>Здравствуйте, 13akaEagle, Вы писали:


AL>
AL>    g.push_back(Game(a, b, "25.12.2006"));
AL>    g.push_back(Game(c, b, "26.12.2006"));   // теперь a == c
AL>    g.push_back(Game(a, c, "27.12.2006"));   // теперь b == c
//в отдалчике контейнер g имеет нужные значения

//здесь всё ещё всё в порядке
AL>    make_heap(g.begin(), g.end(), std::greater<Game>()); //<----- а вот здесь всё портиться
AL>    for (std::vector<Game>::iterator it = g.begin(); it != g.end(); ++it)
AL>    {
AL>        Game& game = static_cast<Game>(*it);
AL>        std::cout << game._first._name << " " << game._second._name << std::endl;
AL>    }
AL>}
AL>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: make_heap или ?
От: a-lex Россия  
Дата: 27.12.06 16:17
Оценка:
Здравствуйте, 13akaEagle, Вы писали:

E>Здравствуйте, a-lex, Вы писали:


AL>>Здравствуйте, 13akaEagle, Вы писали:


AL>>
AL>>    g.push_back(Game(a, b, "25.12.2006"));
AL>>    g.push_back(Game(c, b, "26.12.2006"));   // теперь a == c
AL>>    g.push_back(Game(a, c, "27.12.2006"));   // теперь b == c
E>//в отдалчике контейнер g имеет нужные значения

// тьфу, точно. тут же просто добавляются новые значения...

E>//здесь всё ещё всё в порядке
AL>>    make_heap(g.begin(), g.end(), std::greater<Game>()); //<----- а вот здесь всё портиться

// а вот здесь они начинают копироваться внутри make_heap,
// и происходит то, что я написал в комментариях на пуш_бэки


AL>>    for (std::vector<Game>::iterator it = g.begin(); it != g.end(); ++it)
AL>>    {
AL>>        Game& game = static_cast<Game>(*it);
AL>>        std::cout << game._first._name << " " << game._second._name << std::endl;
AL>>    }
AL>>}
AL>>
Re[6]: make_heap или ?
От: 13akaEagle Россия  
Дата: 27.12.06 16:33
Оценка:
Здравствуйте, a-lex, Вы писали:

AL>Здравствуйте, 13akaEagle, Вы писали:


E>>Здравствуйте, a-lex, Вы писали:


AL>>>Здравствуйте, 13akaEagle, Вы писали:


AL>>>
AL>>>    make_heap(g.begin(), g.end(), std::greater<Game>()); //<----- а вот здесь всё портиться

AL>// а вот здесь они начинают копироваться внутри make_heap,
AL>// и происходит то, что я написал в комментариях на пуш_бэки
AL>>>

    Team tmp = a; //save russia
    a = b; //russia -> litva
    b = tmp; //litva -> russia

А вот здесь всё в порядке. Каким образом они копируются при создании пирамиды?

PS: Сразу оговорюсь, я не знаю что за пирамида(бинарное дерево) ( ) и как там всё реализуется. Просто у меня std::priority_queue<Game> и он работает не очень корректно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: make_heap или ?
От: a-lex Россия  
Дата: 27.12.06 17:05
Оценка: +1
Здравствуйте, 13akaEagle, Вы писали:

Еще раз. Проблема в Game::operator=. Team в данном случае не виновата.

Попробуйте такой код:
Team a("a");
Team b("b");

Game g1(a, b, "");
Game g2(b, b, "");

g1 = g2;  // теперь a == b
Re[8]: make_heap или ?
От: 13akaEagle Россия  
Дата: 28.12.06 12:43
Оценка:
Здравствуйте, a-lex, Вы писали:

AL>Еще раз. Проблема в Game::operator=. Team в данном случае не виновата.

Действительно. А как тогда будет выглядеть правильный Game::operator= ?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: make_heap или ?
От: Кодёнок  
Дата: 28.12.06 13:00
Оценка: 2 (1)
Здравствуйте, 13akaEagle, Вы писали:

AL>>Еще раз. Проблема в Game::operator=. Team в данном случае не виновата.

E>Действительно. А как тогда будет выглядеть правильный Game::operator= ?

Интересный вопрос Единственный способ скопировать ссылку, это присвоить её в конструкторе.
operator=(rhs)
{
  this->~Game();
  new(this) Game(rhs);
  return *this;
}


Этот фрагмент кода используется как пример неверного, потому что если конструктор кинет исключение, объект останется разрушенным. Но в твоем случае объект простой, ничего не кидает, можно использовать. А самый правильный способ, это, очевидно, заменить ссылки на указатели.
Re[9]: make_heap или ?
От: a-lex Россия  
Дата: 28.12.06 13:10
Оценка: 2 (1)
Здравствуйте, 13akaEagle, Вы писали:

AL>>Еще раз. Проблема в Game::operator=. Team в данном случае не виновата.

E>Действительно. А как тогда будет выглядеть правильный Game::operator= ?

Ну, это уже зависит от того, какое поведение класса Game Вы хотите получить.

Вариант 1.

Убираем ссылки (правда ли они нужны? разве мы собираемся менять значения команд через обекты "игра"?) и получаем класс с семантикой "значение" тривиальным способом.
struct Game
{
    Team _first;    // ссылка убрана
    Team _second;   // ссылка убрана
    Score score;
//    TDateTime _datetime;
    std::string _datetime;

    Game(const Team& first, const Team& second, const std::string& datetime);
//убираем -- сойдет и созданный компилятором    Game& operator=(const Game& game);
    friend bool operator>(const Game& left, const Game& rigth);
};


Побочный эффект: теперь каждый объект Game хранит копии объектов Team, а не ссылается на переданные ему в конструкторе команды.

Вариант 2.

Если хотим, чтобы объекты Game не хранили копии Team'ов, а ссылались на уже существующие команды.
struct Game
{
    Team* _first;    // указатель вместо ссылки
    Team* _second;   // указатель вместо ссылки
    Score score;
//    TDateTime _datetime;
    std::string _datetime;

    Game(Team& first, Team& second, std::string datetime);
//убираем -- сойдет и созданный компилятором    Game& operator=(const Game& game);

    friend bool operator>(const Game& left, const Game& rigth);
};


Обратите внимание, что при копировании/присваивании объектов Game копируются указатели на объекты Team. Для облегчения управления их временем жизни вместо голых указателей лучше использовать умные (например, boost::shared_ptr<Team>).

Вариант 3.

struct Game : boost::noncopyable // ну или руками делаем копи-ктор и оператор= приватными
{
    Team& _first;
    Team& _second;
    Score score;
//    TDateTime _datetime;
    std::string _datetime;

    Game(Team& first, Team& second, std::string datetime);
//убираем    Game& operator=(const Game& game);
    friend bool operator>(const Game& left, const Game& rigth);
};


Тут объекты Game получаются некопируемыми. Тогда в контейнере надо хранить (умные) указатели на Game (например, boost::shared_ptr). Алгоритмам типа make_heap придется передавать свой функтор для сравнения указуемых объектов.
Re[10]: make_heap или ?
От: 13akaEagle Россия  
Дата: 28.12.06 13:10
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Интересный вопрос Единственный способ скопировать ссылку, это присвоить её в конструкторе.

Кё>
Кё>operator=(rhs)
Кё>{
  this->>~Game();
Кё>  new(this) Game(rhs);
Кё>  return *this;
Кё>}
Кё>


Кё>Этот фрагмент кода используется как пример неверного, потому что если конструктор кинет исключение, объект останется разрушенным. Но в твоем случае объект простой, ничего не кидает, можно использовать. А самый правильный способ, это, очевидно, заменить ссылки на указатели.

Угу, давно всё сделал на share_ptr.
Просто хотел узнать в чём дело с ссылками...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[10]: make_heap или ?
От: 13akaEagle Россия  
Дата: 28.12.06 13:26
Оценка:
Здравствуйте, a-lex, Вы писали:

AL>

Вариант 2.

AL>Если хотим, чтобы объекты Game не хранили копии Team'ов, а ссылались на уже существующие команды.
AL>
AL>struct Game
AL>{
AL>    Team* _first;    // указатель вместо ссылки
AL>    Team* _second;   // указатель вместо ссылки
AL>    Score score;
AL>//    TDateTime _datetime;
AL>    std::string _datetime;

AL>    Game(Team& first, Team& second, std::string datetime);
AL>//убираем -- сойдет и созданный компилятором    Game& operator=(const Game& game);

AL>    friend bool operator>(const Game& left, const Game& rigth);
AL>};
AL>

С share_ptr и сделал.

AL>Обратите внимание, что при копировании/присваивании объектов Game копируются указатели на объекты Team. Для облегчения управления их временем жизни вместо голых указателей лучше использовать умные (например, boost::shared_ptr<Team>).


AL>

Вариант 3.

AL>
AL>struct Game : boost::noncopyable // ну или руками делаем копи-ктор и оператор= приватными
AL>{
AL>    Team& _first;
AL>    Team& _second;
AL>    Score score;
AL>//    TDateTime _datetime;
AL>    std::string _datetime;

AL>    Game(Team& first, Team& second, std::string datetime);
AL>//убираем    Game& operator=(const Game& game);
AL>    friend bool operator>(const Game& left, const Game& rigth);
AL>};
AL>


AL>Тут объекты Game получаются некопируемыми. Тогда в контейнере надо хранить (умные) указатели на Game (например, boost::shared_ptr). Алгоритмам типа make_heap придется передавать свой функтор для сравнения указуемых объектов.

Об это варианте я даже не знал.

PS: Спасибо всем ответевшим.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.