Ich habe vor einigen Jahren ein Bare-Metal-Projekt (Cortex-M) gestartet. Bei der Projekteinrichtung haben wir uns entschieden, gcc toolchain mit C ++ 11 / C ++ 14 usw. zu verwenden und sogar C ++ - Ausnahmen und rtti zu verwenden.
Wir verwenden derzeit gcc 4.9 von launchpad.net/gcc-arm-embedded (mit einem Problem, das uns derzeit daran hindert, auf eine neuere gcc-Version zu aktualisieren).
Zum Beispiel hatte ich eine Basisklasse und eine abgeleitete Klasse wie diese geschrieben (siehe auch das Beispiel hier ):
%Vor%Damit können die Kunden meiner Klasse jetzt z. B .:
verwenden %Vor%Nun möchte ich die Verwendung der Klasse ein wenig komfortabler machen und habe die folgende Vorlage eingeführt:
%Vor%Und ab jetzt können meine Kunden schreiben:
%Vor% Aber von jetzt an hatte ich eine zunehmende Größe meiner ausführbaren Binärdatei beobachtet. Es scheint, dass gcc Symbolinformationen für jede andere Template-Instanziierung von FixedMemoryStreamWithBuffer
hinzugefügt hat (weil wir aus irgendeinem Grund rtti verwenden).
Könnte es eine Möglichkeit geben, Symbolinformationen nur für bestimmte Klassen / Vorlagen / Template-Instanziierungen loszuwerden?
Es ist in Ordnung, eine nicht portable gcc-only-Lösung dafür zu bekommen.
Aus irgendeinem Grund haben wir uns entschieden, Vorlagen anstelle von Präprozessor-Makros zu bevorzugen. Ich möchte eine Präprozessor-Lösung vermeiden.
Ja, es gibt eine Möglichkeit, die notwendigen Symbole fast bis auf 0
zu bringen: mit der Standardbibliothek. Ihre OutStream
-Klasse ist eine vereinfachte Version von std::basic_ostream
. Dein OutStream::write
ist wirklich nur std::basic_ostream::write
und so weiter. Sehen Sie sich hier an. Der Überlauf wird sehr genau gehandhabt, obwohl der Vollständigkeit halber auch auf underflow
eingegangen wird, d. H. Auf die Notwendigkeit des Datenabrufs; Sie können es als undefined lassen (es ist auch virtual
).
Ähnlich ist Ihr FixedMemoryStream
std::basic_streambuf<T>
mit einer festen Größe (a std::array<T>
) get / put Bereich.
Also, lassen Sie Ihre Klassen einfach von den Standardvariablen erben und Sie werden die binäre Größe abschneiden, da Sie bereits deklarierte Symbole wiederverwenden.
Nun zu template<size_t bufferSize> class FixedMemoryStreamWithBuffer
. Diese Klasse ist sehr ähnlich wie std::array<std::uint8_t, bufferSize>
für die Art und Weise, wie Speicher angegeben und erworben wird. Sie können nicht viel darüber optimieren: Jede Instanziierung ist ein anderer -Typ mit allem, was dazu gehört. Der Compiler kann nicht "verschmelzen" oder etwas Magisches an ihnen vornehmen: Jede Instanz muss ihren eigenen Typ haben.
Entweder greifen Sie auf std::vector
zurück oder Sie haben spezialisierte Teile mit fester Größe wie 32, 128 usw. und für alle Werte dazwischen wählen Sie die richtige; Dies kann vollständig zur Kompilierzeit erreicht werden, also keine Laufzeitkosten.
Beachten Sie zunächst, dass der Compiler auch für jeden FixedMemoryStreamWithBuffer & lt; & gt; separate v-table (sowie RTTI-Informationen) generiert. Typ Instanz, sowie jede Klasse in der Vererbungskette.
Um das Problem zu lösen, würde ich Containment anstelle von Vererbung mit einer Konvertierungsfunktion und / oder einem Operator innerhalb von
empfehlen %Vor%Tags und Links gcc c++11 templates bare-metal