Da eine Unze Erfahrung mehr wert ist als eine Tonne Theorie, habe ich ein kleines Testprogramm für MULTILINE
:
#define MULTILINE(...) #__VA_ARGS__
const char *mstr[] =
{
MULTILINE(1, 2, 3), // "1, 2, 3"
MULTILINE(1,2,3), // "1,2,3"
MULTILINE(1 , 2 , 3), // "1 , 2 , 3"
MULTILINE( 1 , 2 , 3 ), // "1 , 2 , 3"
MULTILINE((1, 2, 3)), // "(1, 2, 3)"
MULTILINE(1
2
3), // "1 2 3"
MULTILINE(1\n2\n3\n), // "1\n2\n3\n"
MULTILINE(1\n
2\n
3\n), // "1\n 2\n 3\n"
MULTILINE(1, "2" \3) // "1, \"2\" \3"
};
Kompilieren Sie dieses Fragment mit cpp -P -std=c++11 filename
zu reproduzieren.
Der Trick dahinter #__VA_ARGS__
ist das __VA_ARGS__
verarbeitet das Komma-Trennzeichen nicht. Sie können es also an den Stringisierungsoperator übergeben. Führende und nachfolgende Leerzeichen werden abgeschnitten, und Leerzeichen (einschließlich Zeilenumbrüche) zwischen Wörtern werden auf ein einziges Leerzeichen komprimiert. Parenthesen müssen ausgeglichen werden. Ich denke, diese Unzulänglichkeiten erklären, warum die Entwickler von C++11, trotz #__VA_ARGS__
sah die Notwendigkeit für rohe String-Literale.
2 Stimmen
Im Allgemeinen sollten Sie keine Stringliterale in den Code einbetten. Für I18N und L10N ist es besser, String-Literale in eine Konfigurationsdatei zu schreiben, die zur Laufzeit geladen wird.
63 Stimmen
Es gibt genügend Fälle, in denen das Einfügen von String-Literalen in den Code kein Problem darstellt: wenn der String nicht verwendet wird, um ihn dem Benutzer darzustellen; d.h.: SQL-Anweisungen, Dateinamen, Namen von Registrierungsschlüsseln, auszuführende Befehlszeilen, ...
4 Stimmen
@Martin: Es kann aber trotzdem nützlich sein, das zu wissen. Ich habe es zum Beispiel gemacht, um komplexe Regexe aufzulösen.