Ich hatte 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.Wie vermeidet man C++ Code Bloat, der von Template Instanziierung und Symboltabelle ausgegeben wird?
Wir verwenden derzeit gcc 4.9 from launchpad.net/gcc-arm-embedded (mit einem Problem, das uns derzeit daran hindern, auf eine neuere GCC-Version zu aktualisieren).
Zum Beispiel würde ich schreibe eine Basisklasse und eine abgeleitete Klasse wie folgt (siehe auch laufendes Beispiel here):
class OutStream {
public:
explicit OutStream() {}
virtual ~OutStream() {}
OutStream& operator << (const char* s) {
write(s, strlen(s));
return *this;
}
virtual void write(const void* buffer, size_t size) = 0;
};
class FixedMemoryStream: public OutStream {
public:
explicit FixedMemoryStream(void* memBuffer, size_t memBufferSize): memBuffer(memBuffer), memBufferSize(memBufferSize) {}
virtual ~FixedMemoryStream() {}
const void* getBuffer() const { return memBuffer; }
size_t getBufferSize() const { return memBufferSize; }
const char* getText() const { return reinterpret_cast<const char*>(memBuffer); } ///< returns content as zero terminated C-string
size_t getSize() const { return index; } ///< number of bytes really written to the buffer (max = buffersize-1)
bool isOverflow() const { return overflow; }
virtual void write(const void* buffer, size_t size) override { /* ... */ }
private:
void* memBuffer = nullptr; ///< buffer
size_t memBufferSize = 0; ///< buffer size
size_t index = 0; ///< current write index
bool overflow = false; ///< flag if we are overflown
};
Damit die Kunden meiner Klasse sind nun in der Lage zB zu verwenden:
char buffer[10];
FixedMemoryStream ms1(buffer, sizeof(buffer));
ms1 << "Hello World";
Jetzt möchte ich würde die Verwendung der Klasse etwas bequemer machen und stellte die folgende Vorlage:
template<size_t bufferSize> class FixedMemoryStreamWithBuffer: public FixedMemoryStream {
public:
explicit FixedMemoryStreamWithBuffer(): FixedMemoryStream(buffer, bufferSize) {}
private:
uint8_t buffer[bufferSize];
};
Und ab jetzt können meine Kunden schreiben:
FixedMemoryStreamWithBuffer<10> ms2;
ms2 << "Hello World";
Aber von jetzt hatte ich 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 rtti aus irgendeinem Grund verwenden).
Könnte es eine Möglichkeit geben, Symbolinformationen nur für bestimmte Klassen/Vorlagen/Template-Instanziierungen zu entfernen?
Es ist in Ordnung, eine nicht portable gcc einzige 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.
Was ist, wenn Sie entfernen die virtuellen Funktionen? Nur polymorphe Objekte können RTTI verwenden. – Quentin
Die virtuellen Funktionen werden definitiv benötigt, weil ich einige andere Klassen habe, die von 'OutStream' abgeleitet sind (z.B. UartStream, TcpStream und so weiter). – Joe
Es besteht nur ein Bedarf, wenn Sie diese abgeleiteten Klassen polymorph (d. H. Durch Ausdrücke des Typs der Basisklasse) verwenden. – Quentin