title: C++11 template function specialization with SFINAE allowing further specializations (error: call of overloaded function is ambiguous)
body: <p>Here's what I'm trying to accomplish (please see comments) and what I have so far.<br>
  This code is compilable and runnable - <a href="http://ideone.com/VCf54u" rel="nofollow noreferrer">ideone link</a>.</p>
  
  <pre><code>#include &lt;type_traits&gt;
  #include &lt;memory&gt;
  #include &lt;iostream&gt;
  
  template&lt;class T&gt;
  class ObjectMustBeCreatedType : public std::false_type {
    // needed for proper static_assert&lt;T&gt; below
  };
  
  // default function that has to be specialized, otherwise compiler error
  template&lt;class T&gt;
  std::shared_ptr&lt;T&gt; CreateObject(const std::string &amp;path) {
      static_assert(ObjectMustBeCreatedType&lt;T&gt;::value, 
                    "please specialize this for your class");
  }
  
  // SFINAE to detect static T::Create function
  template &lt;
      typename T,
      typename = typename std::enable_if&lt;
          std::is_same&lt;
              std::shared_ptr&lt;T&gt;,
              decltype(T::Create(std::string{}))
          &gt;::value
      &gt;::type
  &gt;
  std::shared_ptr&lt;T&gt; CreateObject(const std::string &amp;s) {
      return T::Create(s); // if T::Create is found, call it
  }
  
  // for this class the SFINAE version should be triggered 
  // and CreateObject&lt;AutomaticClass&gt; should be instantiated automatically
  struct AutomaticClass {
      static std::shared_ptr&lt;AutomaticClass&gt; Create(const std::string &amp;s) {
          std::cout &lt;&lt; "AutomaticClass::Create" &lt;&lt; std::endl;
          return std::make_shared&lt;AutomaticClass&gt;();
      }
  };
  
  // for this class CreateObject is manually specialized below
  struct ManualClass {
      ManualClass(const std::string &amp;s) { 
        std::cout &lt;&lt; "ManualClass constructor: " &lt;&lt; s &lt;&lt; std::endl;
      }
  };
  
  // manual CreateObject&lt;ManualClass&gt; specialization
  template&lt;&gt;
  std::shared_ptr&lt;ManualClass&gt; CreateObject(const std::string &amp;s) {
      std::cout &lt;&lt; "CreateObject&lt;ManualClass&gt;" &lt;&lt; std::endl;
      return std::make_shared&lt;ManualClass&gt;(s);
  }
  
  int main() {
      // this works
      CreateObject&lt;ManualClass&gt;("ManualClass test");
  
      // produces compile errors
      CreateObject&lt;AutomaticClass&gt;("AutomaticClass test");
  
      return 0;
  }
  </code></pre>
  
  <p>Now, the problem is that for SFINAE-valid case there now are two functions both matching the template, thus producing following errors:</p>
  
  <pre><code>prog.cpp: In function ‘int main()’:
  prog.cpp:59:59: error: call of overloaded ‘CreateObject(const char [20])’ is ambiguous
           CreateObject&lt;AutomaticClass&gt;("AutomaticClass test");
                                                             ^
  prog.cpp:12:24: note: candidate: std::shared_ptr&lt;_Tp1&gt; CreateObject(const string&amp;) [with T = AutomaticClass; std::__cxx11::string = std::__cxx11::basic_string&lt;char&gt;]
       std::shared_ptr&lt;T&gt; CreateObject(const std::string &amp;path) {
                          ^~~~~~~~~~~~
  prog.cpp:27:24: note: candidate: std::shared_ptr&lt;_Tp1&gt; CreateObject(const string&amp;) [with T = AutomaticClass; &lt;template-parameter-1-2&gt; = void; std::__cxx11::string = std::__cxx11::basic_string&lt;char&gt;]
       std::shared_ptr&lt;T&gt; CreateObject(const std::string &amp;s) {
                          ^~~~~~~~~~~~
  </code></pre>
  
  <p>How can this be fixed in such a way, that:</p>
  
  <ol>
  <li><code>CreateObject&lt;T&gt;</code> remains the same so further specialization for
  user classes looks as clean as possible.</li>
  <li>Therefore, <code>CreateObject&lt;T&gt;</code> must not be moved to class to allow partial template specialization which is easier to do but would look
  dirty.</li>
  <li>Default <code>static_assert</code> error message is kept so user clearly sees that he needs to specialize <code>CreateObject&lt;T&gt;</code> for his class.</li>
  <li>Uses C++11 standard and not a higher one.</li>
  </ol>