title: decltype does not resolve nested vectors. How can I use templates for nested vectors?
body: <p>I am trying to overload the + operator to deal with nested vectors.  I thought the function would call itself until the nested vectors resolve to basic types, but instead I get a huge list of errors when I compile it.  My vector operations that I have defined work for basic types, but not a variable amount of nested vectors.  The only operation that does work for nested vectors is the &lt;&lt; operator.</p>
  
  <p>main.cpp</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;algorithm&gt;
  
  template&lt;typename T1&gt;
  std::ostream&amp; operator&lt;&lt;(std::ostream&amp; stream, std::vector&lt;T1&gt; r){
      if(r.size() == 0){
          return stream;
      }
      else{
          stream &lt;&lt; "(";
          for(int i = 0; i &lt; r.size(); i++){
              if(i &lt; (r.size() - 1)){
                  stream &lt;&lt; r[i] &lt;&lt; ", ";
              }
              else{
                  stream &lt;&lt; r[i] &lt;&lt; ")";
              }
          }
      }
      return stream;
  };
  
  template&lt;typename T1, typename T2&gt;
  auto operator+(const std::vector&lt;T1&gt;&amp; l, const std::vector&lt;T2&gt;&amp; r) 
  -&gt; std::vector&lt;decltype((l[0] + r[0]))&gt;{
      typedef decltype((l[0] + r[0])) type;
      std::vector&lt;type&gt; ans;
      if(l.size() == std::max(l.size(),r.size()))
          std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), std::plus&lt;type&gt;());
      else
          std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), std::plus&lt;type&gt;());
      return ans;
  };
  
  int main(){
  
      std::vector&lt;std::vector&lt;int&gt;&gt; vecvec = {{1,2,3},{4,5,6},{7,8,9}};
      std::vector&lt;int&gt; vec = {1,2,3};
  
      //Both output statements compile
      std::cout &lt;&lt; vec    &lt;&lt; std::endl;
      std::cout &lt;&lt; vecvec &lt;&lt; std::endl;
  
      //Does not compile 
      vecvec = vecvec + vecvec;
  
      //Does compile
      vec = vec + vec;
  
      return 0;
  } 
  </code></pre>
  
  <p>Now I am not able to do type promotion with nested vectors.  I think I need std::plus T1 or std::plus T2 depending on promotion rules.</p>
  
  <pre><code>template &lt;typename T1, typename T2&gt;
  struct Add : std::plus&lt;T1&gt; { };//&lt;- Here
  
  template &lt;typename T1, typename T2&gt;
  struct Add&lt;std::vector&lt;T1&gt;, std::vector&lt;T2&gt;&gt;
  {   
      auto operator()(const std::vector&lt;T1&gt;&amp; l, const std::vector&lt;T2&gt;&amp; r)
          -&gt; std::vector&lt;decltype(Add&lt;T1,T2&gt;{}(l[0], r[0]))&gt;
      {
          using type = decltype(Add&lt;T1,T2&gt;{}(l[0], r[0]));
          std::vector&lt;type&gt; ans;
  
          if(l.size() == std::max(l.size(),r.size()))
              std::transform(r.begin(), r.end(), l.begin(), std::back_inserter(ans), Add&lt;T1,T2&gt;{});
          else
              std::transform(l.begin(), l.end(), r.begin(), std::back_inserter(ans), Add&lt;T1,T2&gt;{});
          return ans;
      };
  };
  
  template &lt;typename T1, typename T2&gt;
  auto operator+(const std::vector&lt;T1&gt;&amp; lhs, const std::vector&lt;T2&gt;&amp; rhs)
      -&gt; decltype(Add&lt;std::vector&lt;T1&gt;, std::vector&lt;T2&gt;&gt;{}(lhs, rhs))
  {
      return Add&lt;std::vector&lt;T1&gt;, std::vector&lt;T2&gt;&gt;{}(lhs, rhs);
  }
  </code></pre>
  
  <p>I tried this and got an output of 2 instead of 2.5.</p>
  
  <pre><code>int main(){
      p(int) e = {1};
      p(double) q = {1.5};
      std::cout &lt;&lt; (e + q) &lt;&lt; std::endl;
      return 0;
  }
  </code></pre>