online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
#include "pxtn.h" #include "fixarray.h" PN_(Basic Tests for Class `fixarray`) int main() { my::fixarray<double> a{3}; a[0] = 2.5; PX_("2.5", a[0]); a[1] = a[0]/2; PX_("1.25", a[1]); a[2] = a[0] + a[1]; PX_("3.75", a[2]); PX_("2.5", *a.data()); }
Die etwas kürzere Übung für nach der Mittagspause ================================================= Schreiben Sie eine Template-Klasse `my::fixarray` welche ein Array fester Größe auf dem Heap anlegt. GENAU WIE beim `std::array` ist die Klasse der Elemente eingeschränkt hinsichtlich dessen, dass diese einen Default-Konstrukor besitzen muss und direkt beim Anlegen alle Elemente mit diesem initialisiert werden. ANDERS ALS beim `std::array` muss die Anzahl der Elemente aber NICHT schon zur Compilezeit sondern erst zur Laufzeit festgelegt werden. ANDERS ALS beim `std::vector` soll die Implementierung NUR EINEN Zeiger sowie sowie die Anzahl der Elemente speichern. Bitte bearbeiten Sie vorerst nur den ersten und zweiten Teil. Den Rest können Sie optional zu einem späteren Zeitpunkt angehen … oder auch nur die letzte Ausbaustufe ansehen. Diese Schritte haben weniger "Modernes C++" zum Inhalt, vielmehr illustrieren sie den grundsätzlichen Ansatz für die Implementierung von Container-Klassen an einem realistischen Beispiel. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1. Teil: Beginnen Sie mit dem in `main.cpp` bzw. `fixarray.h` enthaltenen Minimalumfang. Analysieren Sie den vorgegebenen Code und fügen Sie weitere Testfälle hinzu, sodass ALLE Konstruktoren und Member-Funktionen zumindest EINMAL aufgerufen werden. Frage: Warum ist sind die Member-Funktionen `operator[]` und `data` zweimal mit (scheinbar) ein und derselben Implementierung vorhanden? = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 2. Teil: Ersetzen Sie den bisherigen Zeiger (= native C-style pointer) durch einen `std::unique_ptr` und passen Sie die Member-Funktionen entsprechend an. Frage: Welche Member-Funktionen können Sie nun einfach entfernen? = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 3. Teil: Fügen Sie nun weitere Member-Funktionen hinzu, die bei STL-Containern üblich sind, z.B. * `at()` für den Zugriff mit Indexprüfung; * Kopierkonstruktor und -zuweisung zwischen zwei Objekten der Klasse (dabei aber auch die möglicherweise unterschiedliche Größe beachten!); Und natürlich auch: fügen Sie Tests für alle neu implementierten Features hinzu. (Oder praktizieren Sie striktes TDD: Sie fügen ZUERST den Test hinzu, also was die Klasse unterstützen SOLL, und schreiben erst DANACH die Implementierung.) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 4. Teil: Fügen Sie einen Konstruktor für `std::initializer_list` und sowie für ein generisches Iteratorpaar hinzu. Letzterer soll als ERSTES Argument die Größe erhalten, danach die beiden (Input-) Interatoren. Zusatzfrage: Auf welche "Überaschung" müssen Sie gefasst sein, wenn Sie alle bisherigen Tests im Testcode belassen? = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 5. Teil: Falls nicht schon im letzten Teil geschehen, überlegen Sie nun ob die beiden dort hinzugefügten Konstruktoren evtl. aufeinander aufbauen könnten (also einer der beiden verwendet intern den anderen) und diskutieren Sie ob an dieser Stelle Konstruktor-Vererbung zum Einsatz kommen sollte. Versehen Sie außerdem die Klasse `fixarray` selbst mit der für Container üblichen Iteratorschnittstelle, so dass sie sowohl mit STL-Algorithmen als auch bereichsbasierten `for`-Schleifen verwendbar wird.
#include <memory> namespace my { template<typename T> class fixarray { // replace next line with this: // std::unique_ptr<T[]> arr; // <------------------ // and all related changes, e.g. // no more destructor T *const arr; public: fixarray(std::size_t s) : arr{new T[s]} {} fixarray(const fixarray&) =delete; fixarray(fixarray&& init) : arr{init.arr} { init.arr = nullptr; } fixarray() : arr{nullptr} {} ~fixarray() { delete[] arr; } fixarray& operator=(const fixarray&) =delete; fixarray& operator=(fixarray&& rhs) { if (this != &rhs) { delete[] arr; arr = rhs.arr; } return *this; } T& operator[](std::size_t idx) { return arr[idx]; } const T& operator()(std::size_t idx) const { return arr[idx]; } T* data() { return arr; } const T* data() const { return arr; }; }; }
#ifndef PXT_H #define PXT_H #include <iostream> #include <sstream> #define PX(...)\ ((void)(std::cout << "::: " << __FUNCTION__\ << '[' << __LINE__ << ']'\ << "\t" #__VA_ARGS__ " --> " << (__VA_ARGS__)\ << std::endl)) #define PX_(expect, ...)\ do {\ std::ostringstream result;\ result.flags(std::cout.flags());\ result.precision(std::cout.precision());\ result << (__VA_ARGS__);\ ++PN_::done;\ if (result.str() == expect) break;\ std::cout << "::: " << __FUNCTION__ << '[' << __LINE__ << ']'\ << "\t" #__VA_ARGS__ " --> " << result.str()\ << "\t!= " << expect << std::endl;\ ++PN_::fail;\ } while (false) #define PN_(testname)\ struct PN_ {\ PN_() {\ std::cout << "... " #testname << std::endl;\ }\ ~PN_() {\ std::cout << "=== " << __FILE__ << ": "\ << done << " tests ";\ if (fail) std::cout << ", " << fail\ << " FAILED";\ else std::cout << "passed (OK)";\ std::cout << std::endl;\ }\ static int done, fail;\ } PN_test;\ int PN_::done, PN_::fail; #endif

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue