Template-Funktion



  • Furble Wurble schrieb:

    ´
    Iter i{first};
    std::advance(i, -n);

    wie soll das funktionieren?

    du startest beim ersten und gehst nach "links"?
    da hast du doch schon beim ersten zugriff bereits einen fehler...

    testdriver:

    #include "template.h"
    #include <iostream>
    #include <vector>
    #include <list>
    #include <iterator>
    #include <algorithm>
    #include "genSort.h"
    
    int main(){	
    
    	std::vector<int> v1;
    	std::list<int> l1;
    	for(int i=0; i<20; i++){
    		v1.push_back(i);
    		l1.push_back(i);
    	}
    
    	std::cout << "v1: \n";
    	std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
    	std::cout << "\nl1: \n";
    	std::copy(l1.begin(), l1.end(), std::ostream_iterator<int>(std::cout, " "));
    
    	Shift(v1.begin(), v1.end(), 15, 44);
    	Shift(l1.begin(), l1.end(), 5 , 22);
    
    	std::cout << "\nv1: \n";
    	std::copy(v1.begin(), v1.end(), std::ostream_iterator<int>(std::cout, " "));
    	std::cout << "\nl1: \n";
    	std::copy(l1.begin(), l1.end(), std::ostream_iterator<int>(std::cout, " "));
    
    	return 0;
    }
    

    Ausgabe:

    v1:
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    l1:
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    v1:
    15 16 17 18 19 5 6 7 8 9 10 11 12 13 14 44 44 44 44 44
    l1:
    5 6 7 8 9 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22

    wie gesagt, laut meiner interpretation ist das die aufgabenstellung

    problem liegt nach wie vor im exception handling

    Auszug aus cplusplus: http://www.cplusplus.com/reference/iterator/advance/

    Exception safety
    Throws if any of the arithmetical operations performed on the iterator throws, providing the same level of guarantee as such operations.

    hab das allerding snoch nicht "catchen" können..



  • kk seh grad das das gar net wirklich poasst/(testfälle)

    abe rwie gesagt
    exception handling,
    das andere bekomm ich schon hin


  • Mod

    template<typename Iter>
    void shift(Iter first, Iter last, typename std::iterator_traits<Iter>::difference_type n, const typename std::iterator_traits<Iter>::value_type& v){
      if ( n > 0 )
         std::fill( std::move( std::next( first, n ), last, first ), last, v );
      else if ( n < 0 )
         std::fill( begin, std::move_backward( first, std::next( last, n ), last ), v );
    }
    

    Wenn wir von Exception durch move/Zuweisung absehen, kann das nur fehlschlagen, wenn n zu groß ist, und genau dieser Fall muss laut Aufgabenstellung nicht geprüft werden. Ich sehe also nicht, welches Problem hier eigentlich diskutiert wird.



  • leider kein edit möglich...

    @sone hattest doch recht mit

    shiftit=std::copy(shiftit, end, begin);

    das behebt das problem



  • seldon schrieb:

    Vorsicht, std::size_t ist vorzeichenlos. -n macht nicht, was du erwartest.

    Haha...auch das noch! 🙂
    c++11 wirft std::prev() in den Ring.
    Oder - die Schnittstelle ist fragwürdig - mit Sones difference_type ginge es auch.

    Mir ist die Aufgabe nicht geheuer. 🙂

    @wrock
    ich müsste natürlich die Stelle, ab der Verschoben wird anpassen:

    shift(v1.begin()+18, v1.end(), 15, 44);  // ab der 18. Stelle 15 nach links
        auto it=l1.begin();
        std::advance(it,10);  // ab der 10. Stelle...
        shift(it, l1.end(), 5 , 22);  // ... 5 nach links
    

    Wie dem auch sei: meine Interpretation der Aufgabe ist auch gar nicht wichtig.

    Danke für Eure Aufmerksamkeit 🙂
    cu



  • camper schrieb:

    Wenn wir von Exception durch move/Zuweisung absehen, kann das nur fehlschlagen, wenn n zu groß ist, und genau dieser Fall muss laut Aufgabenstellung nicht geprüft werden. Ich sehe also nicht, welches Problem hier eigentlich diskutiert wird.

    Laut Aufgabenbesprechung soll das template aber trotzdem damit umgehen können falls dieser fall eintritt, aber eben nicht durch die überprüfung von count(n)

    Es muss nicht geprüft werden, ob count größer als die Anzahl der Elemente ist



  • [solved]

    template <typename TItor, typename TValue>
    void Shift(TItor begin, TItor end, size_t count, TValue val){
    
    TItor shiftit=begin;	
    
    for(size_t i =0; i<count; i++){
    
    	std::advance(shiftit, 1);
    	if(shiftit == end){
    		break;
    	}
    
    }
    
    shiftit=std::copy(shiftit, end, begin);
    std::fill(shiftit, end, val);
    
    }
    

  • Mod

    Das scheint mir für RandomAccessIteratoren ineffizient zu sein.



  • stimmt......




  • Mod

    Der Fall begin == end wird auch nicht richtig behandelt, das ist allerdings trivial korrigierbar.



  • camper schrieb:

    Der Fall begin == end wird auch nicht richtig behandelt, das ist allerdings trivial korrigierbar.

    inwiefern nicht richtig, bzw wo siehst du den fehler?

    laut testfall funktioniert alles ohne probleme



  • wrock schrieb:

    camper schrieb:

    Der Fall begin == end wird auch nicht richtig behandelt, das ist allerdings trivial korrigierbar.

    inwiefern nicht richtig, bzw wo siehst du den fehler?

    Selbst wenn im ersten Schleifendurchlauf abgebrochen wird, wird er Iterator shiftit davor noch inkrementiert. Du solltest

    for(size_t i =0; i < count && shiftit != end ; ++i, ++shifit);
    

    schreiben, was aber natürlich nicht Optimal ist wie camper bereits erwähnte.



  • camper schrieb:

    Das scheint mir für RandomAccessIteratoren ineffizient zu sein.

    Nichts, was ein guter Compiler nicht optimieren könnte (zumindest für "normale Container" wie vector, bei deque kann er es leider schon nicht mehr).



  • Sone schrieb:

    Selbst wenn im ersten Schleifendurchlauf abgebrochen wird, wird er Iterator shiftit davor noch inkrementiert. Du solltest

    for(size_t i =0; i < count && shiftit != end ; ++i, ++shifit);
    

    schreiben, was aber natürlich nicht Optimal ist wie camper bereits erwähnte.

    thx, stimmt...wär mir dann spätestens beim kompletten testen aufgefallen

    needforspeed schrieb:

    camper schrieb:

    Das scheint mir für RandomAccessIteratoren ineffizient zu sein.

    Nichts, was ein guter Compiler nicht optimieren könnte (zumindest für "normale Container" wie vector, bei deque kann er es leider schon nicht mehr).

    sicher?
    schließlich läuft er ja immer um eins weiter
    bei einer liste wärs ja egal aber bei einem vector müsste er ja jede stell durchlaufen(was bei einem vector auch direkt möglich wäre)

    sowas checkt ein compiler? 😮 😕



  • wrock schrieb:

    sowas checkt ein compiler? 😮 😕

    Jo. Habs extra getestet. Bei Zeigern und std::vector checkt er es.

    Ändert natürlich nichts dran, dass du es anpassen solltest, denn bei std::deque checkt ers nicht mehr.



  • (Compiler: GCC)



  • needforspeed schrieb:

    wrock schrieb:

    sowas checkt ein compiler? 😮 😕

    Jo. Habs extra getestet. Bei Zeigern und std::vector checkt er es.

    Ändert natürlich nichts dran, dass du es anpassen solltest, denn bei std::deque checkt ers nicht mehr.

    aber...wird das template nicht erst zur laufzeit vollendet?
    da hat doch der compiler nichts mehr verloren oder?



  • Nee, zur Compilezeit.
    Und da hat der Compiler das sagen.


Anmelden zum Antworten