constexpr, static_assert und inlining
Ich habe vorher nachgefragtFunktionsüberladung basierend darauf, ob die Argumente sindconstexpr
. Ich versuche, die enttäuschende Antwort auf diese Frage zu umgehen, um eine intelligentere Assert-Funktion zu erzielen. Das ist ungefähr das, was ich versuche zu tun:
<code>inline void smart_assert (bool condition) { if (is_constexpr (condition)) static_assert (condition, "Error!!!"); else assert (condition); } </code>
Grundsätzlich ist die Idee, dass eine Überprüfung zur Kompilierungszeit immer besser ist als eine Laufzeitüberprüfung, wenn es möglich ist, eine Überprüfung zur Kompilierungszeit durchzuführen. Aufgrund von Inlining und konstantem Falzen kann ich jedoch nicht immer wissen, ob eine Überprüfung der Kompilierungszeit möglich ist. Dies bedeutet, dass es Fälle geben kann, in denenassert (condition)
kompiliert bis aufassert(false)
und der Code wartet nur darauf, dass ich ihn ausführe und diesen Pfad ausführe, bevor ich herausfinde, dass ein Fehler vorliegt.
Wenn es also eine Möglichkeit gäbe, zu überprüfen, ob die Bedingung ein Constexpr ist (aufgrund von Inlining oder anderen Optimierungen), könnte ich anrufenstatic_assert
wenn möglich, und greifen Sie auf eine Laufzeit zurück, wenn dies nicht der Fall ist. Zum Glück hat gcc das Wesentliche__builtin_constant_p (exp)
, was true zurückgibt, wennexp
ist ein constexpr. Ich weiß nicht, ob andere Compiler diese Eigenheiten haben, aber ich hatte gehofft, dass dies mein Problem lösen würde. Dies ist der Code, den ich mir ausgedacht habe:
<code>#include <cassert> #undef IS_CONSTEXPR #if defined __GNUC__ #define IS_CONSTEXPR(exp) __builtin_constant_p (exp) #else #define IS_CONSTEXPR(exp) false #endif // TODO: Add other compilers inline void smart_assert (bool const condition) { static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!"); if (!IS_CONSTEXPR(condition)) assert (condition); } #undef IS_CONSTEXPR </code>
Dasstatic_assert
setzt auf das Kurzschlussverhalten vonor
. ObIS_CONSTEXPR
ist also wahrstatic_assert
kann verwendet werden, und die Bedingung ist!true or condition
, das ist das gleiche wie geradecondition
. ObIS_CONSTEXPR
ist also falschstatic_assert
kann nicht verwendet werden, und die Bedingung ist!false or condition
, das ist genauso wietrue
und dasstatic_assert
wird ignoriert. Wenn dasstatic_assert
kann nicht überprüft werden, weilcondition
ist kein constexpr, dann füge ich eine laufzeit hinzuassert
zu meinem Code als letzter Versuch. Dies funktioniert jedoch nicht dankFunktionsargumente in a nicht verwenden könnenstatic_assert
, auch wenn die Argumente sindconstexpr
.
Dies passiert insbesondere, wenn ich versuche, mit gcc zu kompilieren:
<code>// main.cpp int main () { smart_assert (false); return 0; } </code>
g++ main.cpp -std=c++0x -O0
Alles ist in Ordnung, wird normal kompiliert. Es gibt also kein Inlining ohne OptimierungIS_CONSTEXPR
ist falsch und diestatic_assert
wird ignoriert, also bekomme ich nur eine laufzeitassert
Anweisung (die fehlschlägt). Jedoch,
<code>[david@david-desktop test]$ g++ main.cpp -std=c++0x -O1 In file included from main.cpp:1:0: smart_assert.hpp: In function ‘void smart_assert(bool)’: smart_assert.hpp:12:3: error: non-constant condition for static assertion smart_assert.hpp:12:3: error: ‘condition’ is not a constant expression </code>
Sobald ich Optimierungen einschalte und damit eventuell zulassestatic_assert
ausgelöst zu werden, schlägt fehl, weil ich keine Funktionsargumente in derstatic_assert
. Gibt es eine Möglichkeit, dies zu umgehen (auch wenn es bedeutet, meine eigene zu implementieren?static_assert
)? Ich bin der Meinung, dass meine C ++ - Projekte theoretisch einiges von einer intelligenteren Aussage profitieren könnten, die Fehler so früh wie möglich erkennt.
Es scheint nicht zu machensmart_assert
Ein funktionsähnliches Makro löst das Problem im allgemeinen Fall. Es wird natürlich in diesem einfachen Beispiel funktionieren, abercondition
Möglicherweise stammt eine Funktion aus einer zwei Ebenen höheren Aufrufgrafik (wird dem Compiler jedoch immer noch als eine bekanntconstexpr
aufgrund von Inlining), bei dem das gleiche Problem auftritt wie bei der Verwendung eines Funktionsparameters in astatic_assert
.