Concat-zwei `const char` string-Literale
Ist es möglich, concat zwei string-Literale mit einem constexpr
? Oder anders gesagt, kann man beseitigen-Makros in code wie:
#define nl(str) str "\n"
int main()
{
std::cout <<
nl("usage: foo")
nl("print a message")
;
return 0;
}
Update: Es ist nichts falsch mit der Verwendung "\n"
, jedoch würde ich gerne wissen, ob man kann constexpr
solche zu ersetzen, die Art der Makros.
Was ist falsch mit
Wahrscheinlich am besten zu verwenden
Oder sogar
wahrscheinlich nicht. Wenn Sie möchten, drucken Sie einen Zeilenumbruch, warum würden Sie print ein Zeilenvorschub und flush?
"usage: foo\n" "print a message\n"
?Wahrscheinlich am besten zu verwenden
std::endl
eher als \n
Oder sogar
"usage: foo\nprint a message\n"
?wahrscheinlich nicht. Wenn Sie möchten, drucken Sie einen Zeilenumbruch, warum würden Sie print ein Zeilenvorschub und flush?
std::endl
überlastet ist, wenn Sie wollen einfach nur '\n'
. Also ich glaube nicht, dass std::endl
verwendet werden sollte anstelle von '\n'
.InformationsquelleAutor Micha Wiedenmann | 2012-11-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, es ist durchaus möglich, zu erstellen compile-Zeit-Konstante Zeichenfolgen, und manipulieren Sie mit constexpr Funktionen und Operatoren. Allerdings
Der compiler ist nicht erforderlich, um Konstante Initialisierung von keinem anderen Objekt als statische - und thread-Objekte Dauer. Insbesondere werden temporäre Objekte (die nicht Variablen, und etwas weniger als die automatische Speicherung Dauer) sind nicht erforderlich, um Konstante initialisiert wird, und soweit ich weiß kein compiler macht das für die arrays. Siehe 3.6.2/2-3, die Definition von Konstanten-Initialisierung und 6.7.4 für einige weitere Formulierungen, mit Bezug auf block-Ebene statische Dauer-Variablen. Keines dieser gelten für Provisorien, deren Lebensdauer ist definiert in 12.2/3 und folgende.
So könnte man das erreichen der gewünschten compile-Zeit Verkettung mit:
aber Sie es nicht schaffen mit der Arbeit:
Update:
Aber Sie kann machen es arbeiten mit:
Aber den Häufig verwendeten Satzzeichen ist viel zu hässlich, um es mehr als ein interessanter hack.
(Disclaimer: IANALL, obwohl manchmal ich mag zu spielen auf dem internet. So könnte es einige staubige Ecken der standard das widerspricht der oben genannten.)
(Trotz der Haftungsausschluss, und schob sich durch @DyP, fügte ich ein paar mehr Sprache-lawyerly Zitate.)
Ich möchte hinzufügen 6.7/4, da wir viel mit block-scope von Variablen hier. Und das auch nur erlaubt eine Implementierung zu tun "frühen" init von lokalen static-Speicher-Dauer-Variablen (es ist erforderlich, die initialisiert werden, bevor die ersten block-Eintrag).
12.2/3 "Temporären Objekte zerstört, als der Letzte Schritt in der Bewertung der voll-Ausdruck (1.9) , (lexikalisch) enthält den Punkt, wo Sie erstellt wurden." Es gibt einige Ausnahmen folgt, dass, aber nichts, was erlauben würde, dass die temporären zum permanenten.
Für mich, dynamic storage duration (irrtümlich?) bezogen auf
new
unddelete
- wo würde ich erwarten, dass (praktisch) alle Compiler setzen, um eine temporäre auf dem Stapel.ganz Recht, ich meinte eigentlich "automatisch", sondern 12.2/3 scheint zu sagen, dass Provisorien haben sogar kürzer Leben als das. Ich kann nicht finden, einen Satz zu beschreiben, temporäre Objekt-Lebenszeiten andere als das, also bearbeitete ich die Antwort entsprechend. Unabhängig von der Norm, die wahrscheinlich nicht ermöglichen es einem compiler-Konstante initialisieren eines constexpr temporär-sonst Benutzer-definierten string-Literale wäre viel weniger interessant -- ich bin ziemlich sicher, dass der Compiler eigentlich nicht tun, außer vielleicht für user-defined string-Literale, die noch nicht weitgehend umgesetzt.
InformationsquelleAutor rici
Ein wenig
constexpr
, bestreut mit etwas TMP und ein topping von Indizes gibt mir diese:Live-Beispiel.
Ich würde das Fleisch einige mehr, aber ich muss Los und wollte zu fallen bevor. Sie sollten in der Lage sein zu arbeiten.
Xeo): diese leidet unter dem gleichen problem wie die DyP ' s clevere Lösung, die ist, dass, während es erzeugt die erwartete Ausgabe, die es tatsächlich schafft die strings zur Laufzeit. Um es nicht zu tun, soweit ich weiß, müssen Sie etwas tun, wie
static const auto s = _call to clever constexpr_
. Ich kompiliert habe, die beide diese mit clang 3.2 und g++ 4.7.2 (die 'sorry auf DyP) , Blick auf den Assembler-code generiert.oh du hast Recht, vielen Dank (§3.6.2/2)
Ich war einfach Wiederlesen, der Abschnitt, in der Tat. Afaics, es erlaubt Compiler zu tun Konstanten Initialisierung von Provisorien, aber es ist sicherlich nicht von Ihnen verlangen, so zu tun, und weder das Geräusch noch der gcc tut. Es ist jedoch durchaus möglich, dass andere den text in der standard würde sich auch der Weg der ständigen Initialisierung (die nicht nur beweisen, dass die Beschränkungen in 3.6.2/3 nicht gelten, die möglicherweise in sich selbst schwierig sein).
Der link zu dem Beispiel erscheint, gebrochen zu werden
InformationsquelleAutor Xeo
Auf den ersten Blick C++11 Benutzer-definierten string-Literale zu sein scheinen eine viel einfachere Ansatz. (Wenn, sind Sie zum Beispiel auf der Suche nach einem Weg, um Global aktivieren und deaktivieren newline Injektion zur compile-Zeit)
InformationsquelleAutor Ben Voigt
const char[n]
innerhalb eines constexpr (§7.1.5/3 dcl.constexpr).So (soweit ich weiß), können Sie nicht bekommen eine constexpr, das ist wieder ein
char const*
einer neu errichteten string oder einchar const[n]
. Hinweis: die meisten dieser Einschränkungen nicht, halten Sie für einestd::array
wie bereits von Xeo.Und selbst wenn Sie zurückkehren konnten einige
char const*
ein Rückgabewert ist nicht wörtlich, und nur von benachbarten string-Literale sind verkettet. Dies geschieht in der übersetzung phase 6 (§2.2), die würde ich noch nennen einem preprocessing-phase. Constexpr werden später ausgewertet (ref?). (f(x) f(y)
wof
ist eine Funktion, die einen syntax-Fehler afaik)Aber können Sie sich wieder von Ihrem constexpr fct ein Objekt der etwas anderen Art (mit constexpr ctor oder ein Aggregat) enthält Zeichenfolgen eingesetzt werden können/printed in ein
basic_ostream
.Edit: hier ist das Beispiel. Es ist schon ein bisschen lange o.O
Hinweis: Sie optimieren können, damit nur um eine zusätzliche "\n" hinzufügen " am Ende einer Zeichenfolge. (Dies ist mehr ein generischer Ansatz, den ich nur aus dem Gedächtnis niedergeschrieben.)
Edit2: Eigentlich kann man nicht wirklich optimieren. Erstellen der
arr
Daten Mitglied als ein "array of const char_type" mit dem '\n' (anstatt ein array von string-Literale) verwendet einige ausgefallene variadic template-code, dass ist eigentlich ein bisschen länger (aber es funktioniert, siehe Xeo ' s Antwort).Hinweis:
ct_string_vector
(der name ist nicht gut) speichert Zeiger, es sollte verwendet werden, nur mit Streichern der statische Speicher Dauer (wie Literale oder globalen Variablen). Der Vorteil ist, dass ein string nicht kopiert werden & erweitert durch template-Mechanismen. Wenn Sie eine constexpr zum speichern des Ergebnisses (wie im Beispielmain
), Sie compiler sollte sich beschweren, wenn die übergebenen Parameter sind nicht der statische Speicher Dauer.static constexpr auto
wird es tun. In der Tatstatic const auto
wird es Konstanten initialisiert, wenn möglich. Aber keiner von denen werden lassen, die zweite std::cout Linie handeln in der gleichen Weise wie das makro in der OP, auch nicht in dem Umfang in die Optimierung der add_newline("erste Zeile") in eine compile-time-literal.Sry, aber ich verstehe immer noch nicht, warum
static constexpr
ist ausreichend. Nachdem alle, dies ist ein block-scope static-variable und daher 6.7/4 hält ("Eine Umsetzung zulässig ist,.."). Vielleicht ein chat (kann nicht herausfinden, wie start es o.O)?6.7/4 sagt "Konstante Initialisierung (3.6.2) ein block-scope-Einheit, die mit static storage duration, wenn anwendbar, wird durchgeführt, bevor der block wird zuerst eingegeben." Also, wenn Konstante Initialisierung anwendbar ist, angewendet. "Eine Umsetzung ist erlaubt... andere block-scope von Variablen..." - Anweisung gilt für Initialisierungen, für die die Bedingungen in 3.6.2 nicht gelten. Zumindest ist das meine interpretation, aber wie ich schon sagte, in den disclaimer, IANALL.
InformationsquelleAutor
NÖ, für
constexpr
Sie müssen eine juristische Funktion in den ersten Platz, und die Funktionen können nicht einfügen etc. der string-literal Argumente.Wenn Sie denken über die entsprechende Ausdruck in eine reguläre Funktion, es wäre Arbeitsspeicher zuweisen und verketten von strings - definitiv nicht zugänglich
constexpr
.InformationsquelleAutor Useless