title: constexpr, static_assert, and inlining
body: <p>I previously asked about <a href="https://stackoverflow.com/questions/8936549/constexpr-overloading">function overloading based on whether the arguments are <code>constexpr</code></a>. I'm trying to work around the disappointing answer to that question to make a smarter assert function. This is roughly what I am trying to do:</p>
  
  <pre><code>inline void smart_assert (bool condition) {
      if (is_constexpr (condition))
          static_assert (condition, "Error!!!");
      else
          assert (condition);
  }
  </code></pre>
  
  <p>Basically, the idea is that a compile-time check is always better than a run-time check if it's possible to check at compile time. However, due to things like inlining and constant folding, I can't always know whether a compile time check is possible. This means that there may be cases where <code>assert (condition)</code> compiles down to <code>assert(false)</code> and the code is just waiting for me to run it and execute that path before the I find out there is an error.</p>
  
  <p>Therefore, if there were some way to check whether the condition is a constexpr (due to inlining or other optimizations), I could call <code>static_assert</code> when possible, and fall back on a run-time assert otherwise. Fortunately, gcc has the intrinsic <code>__builtin_constant_p (exp)</code>, which returns true if <code>exp</code> is a constexpr. I don't know if other compilers have this intrinsic, but I was hoping that this would solve my problem. This is the code that I came up with:</p>
  
  <pre><code>#include &lt;cassert&gt;
  #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></pre>
  
  <p>The <code>static_assert</code> relies on the short circuit behavior of <code>or</code>. If <code>IS_CONSTEXPR</code> is true, then <code>static_assert</code> can be used, and the condition is <code>!true or condition</code>, which is the same as just <code>condition</code>. If <code>IS_CONSTEXPR</code> is false, then <code>static_assert</code> cannot be used, and the condition is <code>!false or condition</code>, which is just the same as <code>true</code> and the <code>static_assert</code> is ignored. If the <code>static_assert</code> cannot be checked because <code>condition</code> is not a constexpr, then I add a run-time <code>assert</code> to my code as a last-ditch effort. However, this does not work, thanks to <a href="https://stackoverflow.com/questions/8626055/c11-static-assert-within-constexpr-function/8626450#8626450">not being able to use function arguments in a <code>static_assert</code></a>, <a href="https://stackoverflow.com/questions/9789913/how-to-tell-static-assert-that-constexpr-function-arguments-are-const">even if the arguments are <code>constexpr</code></a>.</p>
  
  <p>In particular, this is what happens if I try to compile with gcc:</p>
  
  <pre><code>// main.cpp
  int main () {
      smart_assert (false);
      return 0;
  }
  </code></pre>
  
  <p><code>g++ main.cpp -std=c++0x -O0</code></p>
  
  <p>Everything is fine, compiles normally. There is no inlining with no optimization, so <code>IS_CONSTEXPR</code> is false and the <code>static_assert</code> is ignored, so I just get a run-time <code>assert</code> statement (that fails). However,</p>
  
  <pre><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></pre>
  
  <p>As soon as I turn on any optimizations and thus potentially allow <code>static_assert</code> to be triggered, it fails because I cannot use function arguments in the <code>static_assert</code>. Is there some way to work around this (even if it means implementing my own <code>static_assert</code>)? I feel my C++ projects could theoretically benefit quite a bit from a smarter assert statement that catches errors as early as possible.</p>
  
  <p>It doesn't seem like making <code>smart_assert</code> a function-like macro will solve the problem in the general case. It will obviously make it work in this simple example, but <code>condition</code> may have come from a function two levels up the call graph (but still becomes known to the compiler as a <code>constexpr</code> due to inlining), which runs into the same problem of using a function parameter in a <code>static_assert</code>.</p>