2016-03-30 10 views
0

Ich definierte eine Klasse FileList, die durchführen erstellen eine Liste von Dateien, die den regulären Ausdruck erfüllen (f_regex Argument).Ein Funktor (inherrited) ist verboten, wenn Sie std :: sort verwenden?

die Liste zu sortieren, eine Instanz von SortBy*** struct ( von FileSorter geerbt) übergeben werden kann.

Das Problem ist std::sort Funktion kann nicht mit dem obigen Code mit der folgenden Fehlermeldung kompiliert werden.

/usr/include/c++/4.8/bits/stl_algo.h:5483:5: error: cannot allocate an object of abstract type ‘FileSorter’

Ich verstehe dieses Verhalten nicht. In meinem engen Wissen, Struktur mit operator() ausgestattet heißt Funktor und es ist ein guter Weg, um mit einer Funktion als ein Objekt umzugehen.

Und wie wir alle wissen, kann beispielsweise von Kind Klasse durch einen Verweis von Elternklasse bezeichnet werden.

Aber das obige Beispiel sagt anders.

Was muss ich ändern, damit der Code funktioniert?

Wenn ich falsche Konzepte über C++ habe, zögern Sie bitte nicht, mich zu schelten.

Vollständige Compile-Fehlermeldungen sind hier.

$ make 
Scanning dependencies of target cpp_factory 
[ 11%] Building CXX object CMakeFiles/cpp_factory.dir/libraries/src/FileLister.cpp.o 
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0: 
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h: In constructor ‘FilesList::FilesList(const string&, const string&, const FileSorter&)’: 
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: error: no matching function for call to ‘sort(std::vector<boost::filesystem::path>::iterator, std::vector<boost::filesystem::path>::iterator, const FileSorter&)’ 
     std::sort(this->begin(), this->end(), fileSorter); 
                 ^
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: note: candidates are: 
In file included from /usr/include/c++/4.8/algorithm:62:0, 
       from /home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:11, 
       from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5: 
/usr/include/c++/4.8/bits/stl_algo.h:5447:5: note: template<class _RAIter> void std::sort(_RAIter, _RAIter) 
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last) 
    ^
/usr/include/c++/4.8/bits/stl_algo.h:5447:5: note: template argument deduction/substitution failed: 
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0: 
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: note: candidate expects 2 arguments, 3 provided 
     std::sort(this->begin(), this->end(), fileSorter); 
                 ^
In file included from /usr/include/c++/4.8/algorithm:62:0, 
       from /home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:11, 
       from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5: 
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: note: template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare) 
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last, 
    ^
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: note: template argument deduction/substitution failed: 
/usr/include/c++/4.8/bits/stl_algo.h: In substitution of ‘template<class _RAIter, class _Compare> void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<boost::filesystem::path*, std::vector<boost::filesystem::path> >; _Compare = FileSorter]’: 
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:109:57: required from here 
/usr/include/c++/4.8/bits/stl_algo.h:5483:5: error: cannot allocate an object of abstract type ‘FileSorter’ 
In file included from /home/ub1404/Application/cpp_factory/libraries/src/FileLister.cpp:5:0: 
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:49:8: note: because the following virtual functions are pure within ‘FileSorter’: 
struct FileSorter{ 
     ^
/home/ub1404/Application/cpp_factory/libraries/include/cpp_factory/files/FileLister.h:51:18: note: virtual bool FileSorter::operator()(const boost::filesystem::path&, const boost::filesystem::path&) const 
    virtual bool operator()(const boost::filesystem::path& p1, const boost::filesystem::path& p2) const =0; 
       ^
make[2]: *** [CMakeFiles/cpp_factory.dir/libraries/src/FileLister.cpp.o] Error 1 
make[1]: *** [CMakeFiles/cpp_factory.dir/all] Error 2 
make: *** [all] Error 2 
+0

Ihr Code kann aufgrund einer nicht deklarierten 'SortByExtension' nicht erstellt werden. –

+0

Sorry @AmiTavory, ich habe die Deklaration von 'SortByExtension' weggelassen, um die Frage zu verkleinern. Entschuldigung, es gab einen Fehler. Vielen Dank. –

+0

Das meiste Prädikat in STL wird von der Kopie übergeben. Könnten Sie Ihre virtuelle Schnittstelle loswerden und stattdessen eine Vorlage verwenden? – Jarod42

Antwort

4

Wenn Sie auf der Unterschrift aussehen, nehmen std::sort sein Vergleichsobjekt von Wert:

template< class RandomIt, class Compare > 
void sort(RandomIt first, RandomIt last, Compare comp); 

Also, wenn Sie schreiben:

std::sort(this->begin(), this->end(), fileSorter); 

Ihr Objekt in Scheiben geschnitten wird, und Sie Am Ende versucht man, eine Funktion zu instanziieren, die eine abstrakte Klasse nach Wert nimmt, also alle Fehler, mit denen man endet.

Was Sie tun müssen, ist sicherzustellen, dass, obwohl sort seinen Vergleich nach Wert nimmt, Sie Ihre durch Bezugnahme übergeben. Zum Glück gibt es dafür eine App! Nur std::ref verwenden:

std::sort(this->begin(), this->end(), std::ref(fileSorter)); 

das gesagt ist, haben Sie wirklich brauchen einen polymorphen Komparator? Wenn Sie nur in verschiedenen Vergleichsfunktion vorbei Objekte in den FilesList Konstruktor, sollten Sie lieber nur eine Funktionsvorlage machen:

template <class Sorter> 
FilesList(const std::string& dir, const std::string& f_regex, Sorter fileSorter) { 
    // ... 
    std::sort(begin(), end(), fileSorter); // now copying is fine 
} 

Auf diese Weise können Sie nur direkt nach vorne in dem, was der Benutzer Pässe und vermeiden virtuellen Versand.

+0

Danke, der Code funktioniert gut mit 'std :: ref', aber mein Code läuft ohne ** C++ 11 **, also habe ich' boost :: ref' stattdessen versucht und es endete mit neuen Fehlern. –

+0

Ich könnte 'boost :: ref' in Verbindung mit' boost :: bind' verwenden. So boost :: bind (boost :: ref (fileSorter), _1, _2) '. –

+1

@JaeJunLEE Das liegt daran, dass 'boost :: reference_wrapper' keinen Aufrufoperator zur Verfügung stellt. Brauchst du * wirklich * einen polymorphen Komparator? Sonst, ja, die 'bind' Lösung entspricht dem was' std :: ref' tat. – Barry

0

Ihr FileSorter-Argument wird standardmäßig auf ein SortByExtension-Objekt und nicht auf ein SortByName-Objekt angewendet.Da Sie nicht die Quelle SortByExtension aufgenommen haben, würde ich durch die Überprüfung, dass die Funktionssignatur von SortByExtension der Funktion Call-Betreiber starten

bool SortByExtension::operator()(const path&, const path&) const 

Wenn es irgendwelche Unterschiede zwischen der Basisklasse und abgeleitete Klasse Funktionssignaturen, die abgeleitete Klasse Die Funktion überschreibt nicht die Basisklasse 1 und die abgeleitete Klasse wird als abstrakte Klasse behandelt.

+0

Danke für die Antwort. Ich habe Teile korrigiert, auf die du zeigst: D. –

Verwandte Themen