go to start Sol W3
|home |print view |recent changes |changed March 31, 2016 |
exact
|You are 54.81.59.211 <- set your identity!

Sections: Feedback Bounded Buffer | Compiler-Warnings (Nr. 1) | !BoundedBuffer<T, SIZE> (Nr. 2) | Member-Types (Nr. 3) | Repetitive Checks (Nr. 4) | Duplizierung bei Berechnungen (Nr. 5) | Fehlende Includes (Nr. 6) | Unnötige Inclues (Nr. 7) | Include Guard (Nr. 8) |

Feedback Bounded Buffer ^

Feedback-Bausteine, mit arbiträrer Nummerierung.

Compiler-Warnings (Nr. 1) ^

Compiler-Warnings sollten nicht ignoriert werden. Zum Beispiel: Wenn eine Funktion einen Rückgabe-Typ hat, braucht sie auch auf jedem Pfad ein return Statement (oder ein throw).

BoundedBuffer<T, SIZE> (Nr. 2) ^

Im Kontext eines Klassen-Templates muss nicht die ganze Template-Id verwendet werden, sofern man die Instanz mit denselben Template-Argumenten verwenden möchte. Konkret am Beispiel von Bounded Buffer: BoundedBuffer ist äquivalent zu BoundedBuffer<T, SIZE>.

Member-Types (Nr. 3) ^

Member-Types sollten abhängig vom verwedeten Container definiert werden.

using container_type = std::array<T, CAPACITY>;
using value_type = typename container_type::value_type;
using reference = typename container_type::reference;
using const_reference = typename container_type::const_reference;
using size_type = size_t;
Dies ermöglicht den einfachen Austausch des zugrunde liegenden Containers. Bei diesen Aliases gibt es jedoch eine Einschränkung. Sie sollten bei Rückgabe-Typen verwendet werden, die vom entsprechenden Rückgabe-Typ des verwendeten Containers abhängig sind. Jedoch muss dies nicht immer der optimale Parameter-Typ auf dem Interfaces des BoundedBuffers sein. Dort sollten die Parameter-Typen unabhängig vom verwendeten Container spezifiziert sein. Beispiel:
reference front() {...}
void push(T const & e) {...}
Grund dafür ist folgender. Der zugrunde liegende Container könnte Spezialisierungen aufweisen, welche nicht mit den erwarteten Typen arbeiten. Ein konkretes Beispiel dafür ist std::vector<bool>, welcher eine optimierte spezialisierung ist, die intern mit Bits arbeitet statt einem bool-Array (oder dies zumindest darf). Da auf diese Bits keine Referenz als bool& zurückgegeben werden kann, wird ein Proxy-Objekt zurückgegeben, welches sich gleich verhalten sollte. Würde nun die push_back-Funktion mit dem entsprechenden Typ-Alias arbeiten, müssten Clients Referenzen auf solche Proxy-Objekte als Argumente verwenden, statt den erwarteten bool values.

Repetitive Checks (Nr. 4) ^

Repetitive Checks zum Zustand des BoundedBuffers, welche in einer Exception resultieren, wenn sie nicht erfüllt sind, könnten in eine passende Funktion ausgelagert werden.

Beispiel, statt:

void push(T const & e) {
  if (full()) {
    throw std::logic_error { "Buffer is full" };
  }
  //push element
}

Besser:

void push(T const & e) {
  throwIfFull();
  //push element
}

void throwIfFull() {
  if (full()) {
    throw std::logic_error { "Buffer is full" };
  }
}

Duplizierung bei Berechnungen (Nr. 5) ^

Magie bei der Berechnung und Anpassung von Indizes können in eine separate Funktion ausgelagert werden, damit man einen schönen Namen dafür hat. Beispiel: (startIndex + noOfElements - 1) % CAPACITY liest sich nicht so toll wie ein Funktionsaufruf indexOfLastElement().

Fehlende Includes (Nr. 6) ^

In der Regel werden folgende Includes benötigt:

Unnötige Inclues (Nr. 7) ^

Es sollte vermieden werden nicht benötigte Includes im Code zu haben.

Include Guard (Nr. 8) ^

Jedes Header-File benötigt einen Include Guard, damit sich in der gleichen Compilation-Unit, um mehrfache Includes des gleichen Header-Files zu vermeiden.


|home |print view |recent changes |changed March 31, 2016 |
exact
|You are 54.81.59.211 <- set your identity!

Sol W3
go to start