Gehen wir davon aus, dass ein Programm das Betriebssystem nutzt um alle Dateien des Startverzeichnisses aufzulisten, deren Name eine bestimmte Buchstabenfolge enthält. Und die ist hard-codet, damit wir das Problem schön mit abdecken.
Normalweise hätten wir jetzt:
(Const Correctness und pass-by-reference ignoriert um das Beispiel zu verkürzen)
void enumerate(std::wstring dir, std::wstring substr); // Unser Arbeitspferd
std::wstring getLaunchDir();
und das wird aufgerufen mit böse in den Quelltext geschriebenen Konstanten:
enumerate(getLaunchDir(), L"foo");
und das ruft unsere tollen gekapselten OS-Funktionen auf, die unter Windows (UTF-16) wären:
EnumFilesW(wchar_t * dir, wchar_t * substr);
CreateFileW(wchar_t *);
OutputStringW(wchar_t *);
und unter Linux (UTF-8):
enumDir(char * dir, char * substr);
open(char *);
print(char *);
Die Implementierungsdetails lassen wir weg; das Ganze kompiliert auf Windows, und … astrein: Wir haben alles mit wchar_t gemacht und müssen nicht konvertieren, weil Windows glücklich ist.
Jetzt kompilieren wir für Linux und … oh scheiße. Linux will ja UTF-8. Was machen wir bloß?! Ja klar! Wir bauen in enumerate(wstring, wstring) Konvertierungen von UCS-32 (denn das ist wstring auf Linux) zu UTF-8 ein! Das überall einzubauen kostet uns drei Entwickler über 8 Tage; das Testen der Konvertierung nochmal zwei Tage, und jetzt klappt es endlich: Jedes Mal, wenn wir enumerate() aufrufen, haben wir eine Shitload Konvertierungen, die kein Schwein braucht (z.B. des Arbeitsverzeichnisses, das wir in UTF-8 vom OS bekommen; für die Rückgabe von getLaunchDir() zu UCS-32 konvertieren; an enumerate() übergeben, und das konvertiert die dann für open() wieder zu UTF-8). Plattformunabhängigkeit ist ein Segen! Und es ist immernoch schneller als Java!
Währenddessen baut Krishty im dunklen Elfenbeinturm folgendes in seine Header:
#ifdef WIN32
typedef wchar_t NativeChar;
# define NATIVE(x) L##x
#else
typedef char NativeChar;
# define NATIVE(x) u8##x
#endif
typedef std::basic_string<NativeChar> NativeString;
und ändert die Prototypen zu:
void enumerate(NativeString dir, NativeString substr);
NativeString getLaunchDir();
und die fest reingeschriebenen Strings zu:
enumerate(getLaunchDir(), NATIVE("foo"));
Krishty kompiliert mit Visual C++ für Windows, und die ganzen NativeStrings werden zu UTF-16-wchar_ts. Das String-Literal wird zu einem UTF-16-L"foo". Und der UTF-8-Quelltext, den Visual C++ nicht kann, wird garnicht angesprungen. Visual C++ sieht effektiv den gleichen Quelltext wie vorher.
Jetzt kompiliert Krishty mit GCC für Linux. Die ganzen NativeStrings werden zu UTF-8-chars. Das String-Literal wird zu einem UTF-8-u8"foo". Krishty muss keine Konvertierungsfunktionen schreiben, testen, und nachbessern, weil überhaupt nicht mehr konvertiert werden muss! Und dass wchar_t zu 4 Bytes wird ist egal, weil es garnicht benutzt wird! Heureka! Welch Korn das blinde Huhn dort getroffen hat!
Aber außerhalb des Elfenbeinturms sind nunmal alle der Meinung, Plattformunabhängigkeite bedeutete, dass meine Strings auf jeder Plattform dieselben Binärdaten haben. Und darum sitzt Krishty auch im Elfenbeinturm und spielt nicht mit anderen Entwicklern in der Sonne: Krishty schreibt alles selber weil Drittbibliotheken grundsätzlich denselben scheiß Fehler machen; egal, mit wie vielen Märchen man die Leute aufzuklären versucht.
Und wenn Krishty nicht gestorben ist, „portiert“ die Firma ihre „gekapselten“ „Wrapper“ noch heute.