Ich habe eine C ++ Klasse, die das Frontend für ein Logging-System ist. Seine Logging-Funktion wird mit den variadischen Vorlagen von C ++ 11 implementiert:
%Vor% Jedes Logging-Backend implementiert seine eigene Version von true_log
, die unter anderem die weitergeleiteten Parameter verwendet, um vsnprintf
aufzurufen. Zum Beispiel:
Alles funktioniert super und ich bin glücklich.
Nun möchte ich eine statische Überprüfung der Parameter log()
hinzufügen: speziell möchte ich das printf-Format-Attribut von GCC verwenden.
Ich fing an, indem ich die Funktion log()
mit __attribute__ ((format (printf, 2, 3)))
markierte (da this
der erste "versteckte" Parameter ist, muss ich die Parameterindizes um eins verschieben). Dies funktioniert nicht, weil es bei einem Kompilierfehler fehlschlägt:
Dann habe ich versucht, der Funktion true_log()
dasselbe Attribut hinzuzufügen. Es kompiliert, aber es wird keine Fehlerüberprüfung durchgeführt: Ich habe versucht, log()
einige ungültige Format / Variablen-Kombinationen zu übergeben, und es wurde keine Warnung ausgegeben. Vielleicht ist diese Art von Prüfung "zu spät", oder anders gesagt, die Information über die Variable ist in der Anrufkette verloren gegangen?
Als letzten Ausweg, wenn ich log()
mit __attribute__ ((format (printf, 2, 0)))
kommentierte, würde ich Warnungen über falsche Formatzeichenfolgen erhalten, aber es würde keine Diagnose für ungültige Format- / Variablenkombinationen ausgegeben.
Zusammenfassung des Problems: Wie kann ich die vollständige Formatprüfung von GCC erhalten, wenn ich die variantenspezifischen Vorlagen von C ++ 11 verwende?
Ich glaube nicht, dass Sie es können. Ich wette, dass GCC nur die Formatzeichenfolge überprüft, wenn es ein Literal ist. Deshalb funktioniert das Setzen des Attributs format
auf true_log
nicht - diese Funktion wird mit dem aufgerufen, was (syntaktisch) wie eine von der Laufzeit bestimmte Zeichenkette aussieht. Würde man es direkt in log
setzen, würde das umgehen, aber würde format
-Attribute benötigen, um variadic template zu unterstützen, was Sie nicht bewiesen haben.
Ich schlage vor, dass Sie sich mehr C ++ - Möglichkeiten anschauen, formatierte Ausgaben zu machen. Es gibt beispielsweise boost::format
, das ähnlich wie printf funktioniert, aber dynamisch überprüft, ob die Anzahl und Typen der Parametertypen mit der Formatzeichenfolge übereinstimmen. Es verwendet jedoch keine variadischen Vorlagen, sondern verbraucht stattdessen Parameter, die ihm (über Operator%) nacheinander zugeführt werden.
Zum Schluss habe ich die Variadischen Templates von C ++ 11 komplett entfernt und eine traditionelle va_list
verwendet.
Tags und Links c++ gcc c++11 variadic-templates function-attributes