title: Enum is not a constexpr?
body: <p>I have such a source code, there is an enumeration which i hope could be evaluated as constexpr, but compiler gives me an error, that it isn't. Why?
  It doesn't matter if EventOrder is an <code>enum</code> or <code>enum class</code>.</p>
  
  <pre><code>#include &lt;limits&gt;
  #include &lt;type_traits&gt;
  
  enum class EventOrder
  {
          Last = 1'000'000,
          Default = 0,
          Logger = -1024,
          First = -1'000'000
  };
  
  template &lt;typename T&gt;
  constexpr inline std::underlying_type_t&lt;T&gt; num(T value) {
          static_assert(std::is_enum&lt;T&gt;::value, "num can only be used on enumeration types");
          return static_cast&lt;std::underlying_type_t&lt;T&gt;&gt;(value);
  }
  
  constexpr EventOrder sum(const EventOrder order, const std::underlying_type_t&lt;EventOrder&gt; orderDelta)
  {
          static_assert(order &gt;= EventOrder::First, "Order Value out of bounds");
          return static_cast&lt;EventOrder&gt;(num(order) + orderDelta);
  }
  
  int main( )
  {
          constexpr EventOrder e = EventOrder::Default;
          sum(e, 2);
          return 0;
  }
  </code></pre>
  
  <p>It gives error:</p>
  
  <pre><code>    $ g++ -std=c++14 EventTest.cc
  EventTest.cc: In function ‘constexpr EventOrder sum(EventOrder, std::underlying_type_t&lt;EventOrder&gt;)’:
  EventTest.cc:23:2: error: non-constant condition for static assertion
    static_assert(order &gt;= EventOrder::First, "Order Value out of bounds");
    ^
  EventTest.cc:23:2: error: ‘order’ is not a constant expression  
  </code></pre>
  
  <p>Why order is not a constexpr?</p>
  
  <p><strong>Edit 1</strong></p>
  
  <p>So is passing arguments as template variables only way to solve that? Or You know some different way?</p>
  
  <pre><code>#include &lt;limits&gt;
  #include &lt;type_traits&gt;
  
  enum class EventOrder
  {
          Last = 1'000'000,
          Default = 0,
          Logger = -1024,
          First = -1'000'000
  };
  
  template &lt;typename T&gt; constexpr inline std::underlying_type_t&lt;T&gt; num(T value)
  {
      static_assert(std::is_enum&lt;T&gt;::value, "num can only be used on enumeration types");
      return static_cast&lt;std::underlying_type_t&lt;T&gt;&gt;(value);
  }
  
  template&lt; typename T &gt;
  constexpr bool LimitedValue(const T value, const T min, const T max)
  {
          return value &gt;= min &amp;&amp; value &lt;= max;
  }
  
  template &lt;EventOrder orderl, std::underlying_type_t&lt;EventOrder&gt; orderr&gt;
  constexpr std::underlying_type_t&lt;EventOrder&gt;  orderSum()
  {
          return num(orderl) + orderr;
  }
  
  template &lt;EventOrder orderl, std::underlying_type_t&lt;EventOrder&gt; orderr&gt;
  constexpr EventOrder order()
  {
          static_assert(LimitedValue(orderSum&lt;orderl, orderr&gt;(), num(EventOrder::First), num(EventOrder::Last)), "order out of baunds");
          return static_cast&lt;EventOrder&gt;(orderSum&lt;orderl, orderr&gt;());
  }
  
  int main()
  {
          EventOrder e = order&lt;EventOrder::Default, 2&gt;();
  
  }
  </code></pre>