mixing CRTP with SFINAE
<p>I have a <code>base</code> taking derived type as template parameter. The following code works as expected. instantiation of <code>base&lt;non_default_impl&gt;</code> uses <code>non_default_impl::data_t</code> and <code>base&lt;default_impl&gt;</code> throws compilation error because <code>event_data</code> is only a forward declaration.</p>

<pre><code>template &lt;typename T&gt;
struct event_data;

template&lt;typename T&gt;
struct tovoid {
    typedef void type;
};

template &lt;typename T, typename enable = void&gt;
struct get_data{
  typedef event_data&lt;T&gt; type;
};

template &lt;typename T&gt;
struct get_data&lt;T, typename tovoid&lt;typename T::data_t&gt;::type &gt;{
  typedef typename T::data_t type;
};

template &lt;typename T&gt;
struct base{
    typedef typename get_data&lt;T&gt;::type data_type;

    base(){
        data_type();
    }
};

struct non_default_impl{
    struct data{};

    typedef data data_t;
};
struct default_impl{

};

int main(){
    base&lt;non_default_impl&gt; e1;
    base&lt;default_impl&gt; e2;
    return 0;
}
</code></pre>

<p>But when <code>non_default_impl</code> inherits from <code>base&lt;non_default_impl&gt;</code> SFINAE substitutes to the forward declaration.</p>

<pre><code>struct non_default_impl: public base&lt;non_default_impl&gt;{
    struct data{};

    typedef data data_t;
};

int main(){
    non_default_impl e1;
//  base&lt;default_impl&gt; e2;
    return 0;
}
</code></pre>

<blockquote>
  <p>prog.cpp: In instantiation of 'base::base() [with T =
  non_default_impl]':</p>
  
  <p>prog.cpp:28:8:   required from here</p>
  
  <p>prog.cpp:24:3: error: invalid use of incomplete type 
  'base::data_type {aka struct
  event_data}'    data_type();</p>
</blockquote>

<p>How to make this work. I want if the derived class have a <code>data_t</code> typedef use that otherwise use <code>event_data&lt;derived_type&gt;</code></p>

<p><a href="https://ideone.com/WOIsn0" rel="nofollow">https://ideone.com/WOIsn0</a></p>