title: C++ template instantiation with shared_ptr to const T
body: <p>Suppose I have a class </p>
  
  <pre><code>template &lt;typename T&gt;
  class A {
   public:
    template &lt;typename V&gt;
      void f(std::tr1::shared_ptr&lt;const std::vector&lt;V&gt; &gt; v1, 
             std::tr1::shared_ptr&lt;const std::vector&lt;float&gt; &gt; v2) {}
  };
  </code></pre>
  
  <p>The following does not compile:</p>
  
  <pre><code> A&lt;string&gt; a;
    std::tr1::shared_ptr&lt;std::vector&lt;float&gt; &gt; v1(new std::vector&lt;float&gt;());
    std::tr1::shared_ptr&lt;std::vector&lt;float&gt; &gt; v2(new std::vector&lt;float&gt;());
    a.f(v1, v2);
  </code></pre>
  
  <p>The compiler error is:</p>
  
  <pre><code>error: no matching function for call to 'A&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;::f(std::tr1::shared_ptr&lt;std::vector&lt;float, std::allocator&lt;float&gt; &gt; &gt;&amp;, std::tr1::shared_ptr&lt;std::vector&lt;float, std::allocator&lt;float&gt; &gt; &gt;&amp;)'
  </code></pre>
  
  <p>The compiler could not make <code>std::tr1::shared_ptr&lt;std::vector&lt;float&gt; &gt;</code>  into 
  <code>std::tr1::shared_ptr&lt;const std::vector&lt;float&gt; &gt;</code> for the first argument. Yet it could for the second (non-template argument).</p>
  
  <p>One solution to this is to change the call to f(), call it like this <code>f&lt;float&gt;(...)</code>.<br>
  Another solution is to declare v1 as shared_ptr to <code>const vector&lt;float&gt;.</code> </p>
  
  <ol>
  <li>Why is template instantiation behaving so differently here?</li>
  <li>My understanding of having a <code>shared_ptr&lt;const T&gt;</code> as argument to a method is that the method cannot change what the <code>shared_ptr</code> is pointing to. If we change the <code>shared_ptr</code>s to raw pointers and <code>v1</code>, <code>v2</code> as raw pointers to <code>vectors</code>, then the code will compile fine. What is it about <code>shared_ptr</code>s that breaks template deduction?</li>
  </ol>