title: MSVC failed to compile when converting a base type to a derived type in a constant-expression
body: <p>Code:</p>
  
  <pre><code>#include &lt;cstddef&gt;
  
  template &lt;typename value_type, typename iterator_type&gt;
  class array_iterator_base
  {
  protected:
      value_type *ptr;
  
  public:
      constexpr array_iterator_base() : ptr(nullptr) {}
      constexpr iterator_type &amp;operator++()
      {
          ++ptr;
          return *static_cast&lt;iterator_type *&gt;(this); // [1]
      }
  };
  
  template &lt;typename value_type&gt;
  class array_iterator : public array_iterator_base&lt;value_type, array_iterator&lt;value_type&gt;&gt;
  {
  public:
      constexpr array_iterator(value_type *ptr)
      {
          this-&gt;ptr = ptr;
      }
  };
  
  template &lt;typename value_type, std::size_t Size&gt;
  class array
  {
  public:
      using iterator = array_iterator&lt;value_type&gt;;
  
      value_type m_data[Size];
      constexpr iterator begin() { return iterator(m_data); }
  };
  
  class Demo
  {
      using storage = array&lt;int, 3&gt;;
      using iterator = typename storage::iterator;
  
  private:
      storage m_arr = { 1, 2, 3 };
      iterator m_iter = m_arr.begin();
  
  public:
      constexpr Demo() {}
      constexpr void field()
      {
          ++m_iter; // MSVC: failed
      }
      constexpr void local_variable()
      {
          storage arr = { 1,2,3 };
          iterator iter = arr.begin();
          ++iter; // MSVC: OK
      }
  };
  
  constexpr int ok()
  {
      Demo demo;
      demo.local_variable();
      return 1;
  }
  
  constexpr int error()
  {
      Demo demo;
      demo.field();
      return 1;
  }
  
  int main()
  {
      constexpr int x = ok();
      // GCC: OK
      // Clang: OK
      // MSVC: OK
  
      constexpr int y = error(); // [2]
      // GCC: OK
      // Clang: OK
      // MSVC: error
  }
  </code></pre>
  
  <p>Error at line <code>[2]</code> due to line <code>[1]</code>:</p>
  
  <pre><code>Expression did not evaluate to a constant.
  Failure was caused by cast of object of dynamic type
      array_iterator&lt;value_type&gt;
  to type
      iterator_type
  with
      [value_type=int]
      [iterator_type=array_iterator&lt;int&gt;]
  </code></pre>
  
  <p>I am writing an array class myself. I decide to write an array iterator base class so that any array iterator class can just inherit from it to save some keystrokes. To do this, I must cast the base class to the derived iterator class when there is a need to return the iterator itself, so there is the <code>return *static_cast&lt;iterator_type *&gt;(this);</code> in the <code>iterator_type &amp;operator++()</code> overload. </p>
  
  <p>However, in a <code>constexpr</code> context, MSVC failed to compile when the iterator is a field in a class but compiled successfully when the iterator is a local variable. The error message said that the expression is not constant because the function call involves casting a dynamic type (see above).</p>
  
  <p>GCC and Clang compiled successfully in both cases.</p>
  
  <p>Interestingly, in Visual Studio, the value of <code>y</code> can actually be previewed (by hovering the cursor on it) just like any other <code>constexpr</code> variable (which makes me think that MSVC is probably wrong).</p>
  
  <p>Edit: The latest preview version of MSVC still does not compile.</p>
  
  <p>Edit: I have reported this bug to Microsoft <a href="https://developercommunity.visualstudio.com/content/problem/936091/compile-time-error-when-converting-from-base-type.html" rel="nofollow noreferrer">here</a>.</p>
  
  <p>Questions:</p>
  
  <ol>
  <li><p>Which compiler is correct according to the standard?</p></li>
  <li><p>Is there a better way to do what I am doing (i.e. writing a base class for iterator classes to inherit from)?</p></li>
  </ol>