Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Jenda 15. 03. 2012, 23:55:49
-
Ahoj, snazim se setridit vector s ukazateli, mam nasledujici kod, ktery jsem pokoumal poruznu na forech
class TZaznam
{
public:
char Zanr;
char Typ;
char Novinka;
};
class TPlaylist
{
public:
vector <TZaznam*>PoleZaznamu;
bool PorovnejRetezec( const TZaznam *prvni, const TZaznam *druhy );
};
void TPlaylist::SetridPoleZaznamu()
{
sort( PoleZaznamu.begin(), PoleZaznamu.end(), PorovnejRetezec);
}
Bohuzel vsak dostavam nasledujici hlaseni od prekladace
|32|error: no matching function for call to 'sort(__gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, __gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, <unresolved overloaded function type>)'|
Danemu hlaseni bohuzel vubec nerozumim a ani strejda google mi nedal odpoved. Rad bych tedy poprosil nekoho o radu.
Predem moc dekuji
-
Porovnavacia funkcia ocakava pointer na typ triedenych prvkov, kedze prvky vectoru su pointre na TZaznam, porovnavacia funkcia ocakava pointer na pointer na TZaznam a teda:
bool PorovnejRetezec( const TZaznam **prvni, const TZaznam **druhy );
o hviezdicku viac :)
-
Ta hláška říká jednoduše to, že žádná metoda std::sort pro dané parametry neexistuje. Třetí parametr pro std::sort totiž musí být funktor, zatímco vy tam máte metodu, která dokonce ani není statická.
Porovnavacia funkcia ocakava pointer na typ triedenych prvkov, kedze prvky vectoru su pointre na TZaznam, porovnavacia funkcia ocakava pointer na pointer na TZaznam a teda:
bool PorovnejRetezec( const TZaznam **prvni, const TZaznam **druhy );
o hviezdicku viac :)
Porovnávací funktor dostává reference na porovnávané prvky.
-
dekuji za promtni odpovedi,
metodu jsem tedy uvedl jako statickou a pridal ukazatel na ukazatel,
static bool PorovnejRetezec( const TZaznam **prvni, const TZaznam **druhy ){return true;}
presto me vsak jeste neco nehraje
cannot convert 'TZaznam* const' to 'const TZaznam**' in argument passing
nekde jsem jeste videl pouziti "ptr_fun()" ale to si nejsem uplne jisty co by to melo delat. Tuzim ze asi neco jako ukazatel na funkci.
-
Co treba takhle (viz Sten):
#include <vector>
#include <algorithm>
class TZaznam
{
public:
char Zanr;
char Typ;
char Novinka;
};
using namespace std;
class TPlaylist
{
struct {
bool operator()(const TZaznam *prvni, const TZaznam *druhy );
} PorovnejZaznam;
public:
vector <TZaznam*>PoleZaznamu;
void SetridPoleZaznamu()
{
sort( PoleZaznamu.begin(), PoleZaznamu.end(), PorovnejZaznam);
}
};
-
bohuzel opet error:
error: no matching function for call to 'sort(__gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, __gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, TPlaylist::<anonymous struct>&)'|
-
Ono zrejme take zalezi na verzi prekladace. Ja to zkusil s g++ verze 4.6. S nim je to v poradku. Prekladac intel composer xe (sp1, 8.273) tj. icpc to neprelozi a dava stejnou chybovou hlasku jako u Vas. Staci mu ale vnutit novy standard pomoci -std=c++0x a pak to jde.
Nasledujici priklad (doplneni predchoziho) je vyzkousen v linuxu s g++ a s icpc -std=c++0x. Jaky prekladac pouzivate Vy?
P.S. miluji prenositelnost programu C/C++ :)
#include <iostream>
#include <vector>
#include <algorithm>
class TZaznam
{
public:
char Zanr;
char Typ;
char Novinka;
};
using namespace std;
class TPlaylist
{
struct {
bool operator()(const TZaznam *prvni, const TZaznam *druhy ) {
return prvni->Zanr < druhy->Zanr;
};
} PorovnejZaznam;
public:
vector <TZaznam*>PoleZaznamu;
void SetridPoleZaznamu()
{
std::sort( PoleZaznamu.begin(), PoleZaznamu.end(), PorovnejZaznam);
}
};
int main() {
TPlaylist pl;
TZaznam *z;
z = new TZaznam;
z-> Zanr = 'r';
pl.PoleZaznamu.push_back(z);
z = new TZaznam;
z-> Zanr = 'p';
pl.PoleZaznamu.push_back(z);
z = new TZaznam;
z-> Zanr = 's';
pl.PoleZaznamu.push_back(z);
cout << "Puvodni playlist:" << endl;
for (int i = 0; i< pl.PoleZaznamu.size(); i++)
cout << pl.PoleZaznamu[i]->Zanr << " ";
cout << endl;
// Setridim
pl.SetridPoleZaznamu();
cout << "Setrideny playlist:" << endl;
for (int i = 0; i< pl.PoleZaznamu.size(); i++)
cout << pl.PoleZaznamu[i]->Zanr << " ";
cout << endl;
return 0;
}
S g++:
petanque:~/Vyuka/PIA/STL$ g++ sort.cpp
petanque:~/Vyuka/PIA/STL$ ./a.out
Puvodni playlist:
r p s
Setrideny playlist:
p r s
s intelem:
petanque:~/Vyuka/PIA/STL$ icpc -std=c++0x sort.cpp
Warning #2928: the __GXX_EXPERIMENTAL_CXX0X__ macro is disabled when using GNU version 4.6 with the c++0x option
petanque:~/Vyuka/PIA/STL$ ./a.out
Puvodni playlist:
r p s
Setrideny playlist:
p r s
-
Dekuji za pomoc , uz to funguje, stacilo nainstalovat novou verzi mingw. Prekladal jsem to na verzi, ktera se automaticky nainstalovala s codeblocs tusim 4.5
-
Tak jeste se vyskytl jeden problem a to s iteratory, ale to bude nejspis moje chyba sintaxe. Snazim se setridit jiz jenom cast toho pole pointeru na objekty.
c:\programovani\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.6.2\include\c++\bits\stl_iterator_base_types.h|166|error: no type named 'iterator_category' in 'class TZaznam'|
void TPlaylist::SetridPoleZaznamu()
{
stable_sort( PoleZaznamu.begin(), PoleZaznamu.end(), PorovnejAlbum); //tento radek funguje bezchybne
stable_sort( PoleZaznamu.begin(), PoleZaznamu.end(), PorovnejZanr); //tento radek take funguje
vector<TZaznam*>::iterator Aktualni,Predni,Zadni; //vytvarim iteratory
Predni=PoleZaznamu.begin();
if (PoleZaznamu.size()>1)
{
for ( Aktualni=Predni ; Aktualni < PoleZaznamu.end()-1; Aktualni++ )
{
Zadni=Aktualni;
if (((**Predni).NazevAlba).compare((**Zadni++).NazevAlba) != 0) //porovnani se zda byt take v poradku
{
stable_sort(**Predni, **Aktualni, PorovnejPisen); //zde se generuje chyba
Predni=Aktualni++;
}
}
}
}
Budu velice vdecen za jakykoliv napad co stim.
-
for ( Aktualni=PoleZaznamu.begin() ; Aktualni != PoleZaznamu.end(); ++Aktualni)
end() vrací vždy jeden prvek za posledním takže stačí porovnávat na != a nemusí být relace <
pro inkrementaci iterátoru používej preincrement ++iter namísto iter++ pro maximální přenositelnost, ne každý objekt implementuje postincrement operátor, takže některé části kódu rozepiš na dva řáky
Predni = Aktualni;
++Aktualni;
sice to je méně kompaktní, ale až to bude někdo někdy krokovat v debuggeru, tak tě nebude proklínat
mrkni jak je udělané for_each
http://www.cplusplus.com/reference/algorithm/for_each/
pro inspiraci
-
bohuzel opet error:
error: no matching function for call to 'sort(__gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, __gnu_cxx::__normal_iterator<TZaznam**, std::vector<TZaznam*, std::allocator<TZaznam*> > >, TPlaylist::<anonymous struct>&)'|
Problem je v tom, ze podle starsiho standardu C++ nelze pouzit "nepojmenovany" typ jako template argument.
Tj, "struct { ... }" jakozto typ funktoru PorovnejZaznam v template funkci std::sort().
Vyresis to napriklad jednoduse pojmenovanim typu funktoru:
struct TPorovnejZaznam { ... } PorovnejZaznam;
-
for ( Aktualni=PoleZaznamu.begin() ; Aktualni != PoleZaznamu.end(); ++Aktualni)
end() vrací vždy jeden prvek za posledním takže stačí porovnávat na != a nemusí být relace <
pro inkrementaci iterátoru používej preincrement ++iter namísto iter++ pro maximální přenositelnost, ne každý objekt implementuje postincrement operátor, takže některé části kódu rozepiš na dva řáky
Predni = Aktualni;
++Aktualni;
Doporučil bych:
for ( ...::iterator Aktualni=PoleZaznamu.begin(), Konec=PoleZaznamu.end() ; Aktualni != Konec; ++Aktualni)
Volání metody .end() nemusí mít konstantní složitost a je zbytečné jej opakovat v každém kroku.
-
Parada, moc me to pomohlo. Velice vsem dekuji