title: C++ dynamic_cast to forward declared class template compiles, but is it safe?
body: <p>The following code compiles and gives result as one would expect in (GCC and clang):</p>
  
  <pre><code>template &lt;typename T&gt; struct Derived;
  
  struct Base
  {
      template &lt;typename T&gt;
      void foo(T * const t)
      {
          dynamic_cast&lt;Derived&lt;T&gt; * const&gt;(this)-&gt;bar(t);
      }
  };
  
  template &lt;typename T&gt;
  struct Derived : Base
  {
      void bar(T const *) const { }
  };
  </code></pre>
  
  <p>The code dispatches a call to <code>foo</code> in <code>Base</code> to <code>bar</code> in <code>Derived</code>.</p>
  
  <p>As a point of reference, the following code does not compile:</p>
  
  <pre><code>struct Derived2;
  
  struct Base2
  {
      template &lt;typename T&gt;
      void foo(T * const t)
      {
          dynamic_cast&lt;Derived2 * const&gt;(this)-&gt;bar(t);
      }
  };
  
  struct Derived2 : Base2
  {
      template &lt;typename T&gt;
      void bar(T const *) const { }
  };
  </code></pre>
  
  <p>GCC provides the following diagnostic:</p>
  
  <pre><code>main.cpp: In member function 'void Base2::foo(T*)':
  main.cpp:126:45: error: invalid use of incomplete type 'struct Derived2'
           dynamic_cast&lt;Derived2 * const&gt;(this)-&gt;bar(t);
                                               ^
  main.cpp:119:8: note: forward declaration of 'struct Derived2'
   struct Derived2;
          ^
  </code></pre>
  
  <p>The C++14 standard states in the section on the One Definition Rule, the following:</p>
  
  <blockquote>
    <p>5 Exactly one definition of a class is required in a translation unit
    if the class is used in a way that requires the class type to be
    complete. <br>
    [ Example: the following complete translation unit is
    well-formed, even though it never defines X: <br>
    struct X; // declare X as a struct type <br>
    struct X* x1; // use X in pointer formation <br>
    X* x2; // use X in pointer formation <br>
    —end example ] <br>
    [ Note: The rules for
    declarations and expressions describe in which contexts complete class
    types are required. A class type T must be complete if:
    (5.1) — an object of type T is defined (3.1), or <br>
    (5.2) — a non-static class data member of type T is declared (9.2), or <br>
    (5.3) — T is used as the object type or array element type in a new-expression (5.3.4), or <br>
    (5.4) — an lvalue-to-rvalue conversion is applied to a glvalue referring to an object of type T (4.1), or <br>
    (5.5) — an expression is converted (either implicitly or explicitly) to type T (Clause 4, 5.2.3, 5.2.7, 5.2.9, 5.4), or <br>
    (5.6) — an expression that is not a null pointer constant, and has type other than cv void*, is converted to the type pointer to T or reference to T using a standard conversion (Clause 4), a dynamic_cast (5.2.7) or a static_cast (5.2.9), or ...</p>
  </blockquote>
  
  <p>This seems to state that the first example is not legal. This is construct ill-formed? If so, why am I not getting an error?</p>