title: Enable_if for template function specialization
body: <p>I was playing with Decorator pattern in C++. After making things work like in a book I decided to create a template function (called 'decorate') to help me construct the decorated object based on the decorator class, concrete class and interface class. </p>
  
  <p>Basic template function worked perfect. But then I decided that I would like to have also an empty implementation of decorator class, which would not do anything else but calling the concrete object method. This worked and I could stick to this design, but I wasn't very satisfied by the fact that when the empty decorator is used, I would still have a virtual call there, which in fact does nothing but calling another virtual method. I wanted to avoid such unnecessary indirection and I decided to specialize my template function so that when the empty decorator is used, it returns undecorated object (concrete object). 
  I wanted to specialize my template function using enable_if but somehow it doesn't want to compile. I must be doing something wrong. Please help me. What is wrong with my code below?</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;memory&gt;
  #include &lt;type_traits&gt;
  using namespace std;
  
  struct IA {
      virtual ~IA() {}
      virtual void doSth() = 0;
  };
  
  struct ConcreteA : public IA
  {
      void doSth() override 
      {
           cout &lt;&lt; "concrete: doSth" &lt;&lt; endl;
      }
  };
  
  struct LoggingDecoratorA : public IA {
      LoggingDecoratorA(unique_ptr&lt;IA&gt; pia) : _pia(move(pia)) {}
      void doSth() override 
      {
           cout &lt;&lt; "calling doSth" &lt;&lt; endl;
          _pia-&gt;doSth();
      }
      unique_ptr&lt;IA&gt; _pia;
  };
  
  struct EmptyDecoratorA : public IA {
      EmptyDecoratorA(unique_ptr&lt;IA&gt; pia) : _pia(move(pia)) {}
      void doSth() override 
      {
          _pia-&gt;doSth();
      }
      unique_ptr&lt;IA&gt; _pia;
  };
  
  void fun(IA* pia)
  {
      pia-&gt;doSth();
  }
  
  template&lt;typename Decorator, typename Concrete, typename Interface, typename X = enable_if_t&lt;!is_same&lt;Decorator, EmptyDecoratorA&gt;::value&gt;&gt;
  unique_ptr&lt;Interface&gt; decorate()
  {
      return make_unique&lt;Decorator&gt;((make_unique&lt;Concrete&gt;()));
  }
  
  template&lt;typename Decorator, typename Concrete, typename Interface, typename X = void&gt;
  unique_ptr&lt;Interface&gt; decorate()
  {
      return make_unique&lt;Concrete&gt;();
  }
  
  int main()
  { 
      auto pia = decorate&lt;LoggingDecoratorA, ConcreteA, IA&gt;();
      fun(pia.get());
  }
  </code></pre>