title: Static assertion if possible, dynamic assertion otherwise?
body: <p>Let's say I have a template function that takes an integer and a const reference to an instance of type T. Now depending on the integer, only some T's are acceptible, otherwise an exception is thrown at runtime.</p>
  
  <p>If all uses of this function would use constant integers, it would be possible to make the int a template parameter and use a static assertion to check if it is acceptable. So instead of <code>func(1,c)</code> one would use <code>func&lt;1&gt;(c)</code> and would gain compile-time type checking. Is there any way to write <code>func(1,c)</code> and still keep the compile-time check, while also being able to write <code>func(i,c)</code> and use a dynamic assertion? The goal is to make it transparent to the developer. It would simply be great to add this safety without bothering the developers about things like compile-time constants. They'd probably only remember that <code>func(1,c)</code> always works and use that, avoiding the check.</p>
  
  <p><strong>How can I define a function with a static assertion whenever possible and a dynamic assertion otherwise?</strong></p>
  
  <hr>
  
  <p>The following code shows the solution for GCC by <strong>Ivan Shcherbakov</strong>:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;cassert&gt;
  
  template&lt;typename T&gt;
  void __attribute__((always_inline)) func(const int&amp; i, const T&amp; t);
  
  void compile_time_error_() __attribute__((__error__ ("assertion failed")));
  
  template&lt;&gt;
    void __attribute__((always_inline))
    func(const int&amp; i, const float&amp; t)
  {
      do {
          if (i != 0) {
              if (__builtin_constant_p(i)) compile_time_error_();
              std::cerr &lt;&lt; "assertion xzy failed" &lt;&lt; std::endl;
              exit(1);
          }
      } while (0);
      func_impl&lt;float&gt;(i,t);
  }
  </code></pre>
  
  <p>This will only allow the combination of i=0 and T=float. For other combinations a good way would be creating a Macro that produces the code of <code>template&lt;&gt; func(const int&amp; i, const T&amp; t)</code> with T and i != 0 replaced.</p>