title: C++ Concepts with multiple template arguments
body: <p>Bjarne Stroustrup recently published a <a href="http://www.stroustrup.com/good_concepts.pdf" rel="noreferrer">report</a> on C++ Concepts where he mentions something that seemed surprising to me. The example (in Section 7.1) uses "shorthand template notation" and essentially goes like this:</p>
  
  <pre><code>void foo1(auto x,auto y);                // x and y may have different types  (1)
  void foo2(SomeConcept x,SomeConcept y);  // x and y must have the same type   (2)
  </code></pre>
  
  <p>To me personally, this seems <em>very</em> counter-intuitive; in fact, I would expect foo2 to accept values x,y of different types as long as the respective types satisfy SomeConcept. Note that the programmer can always explicitly specify his intent by writing one of the following:</p>
  
  <pre><code>template &lt;SomeConcept T&gt; void foo2(T x, T y);                   // (3)
  template &lt;SomeConcept T1,SomeConcept T2&gt; void foo2(T1 x,T2 y);  // (4)
  </code></pre>
  
  <p>Intuitively, I would expect the shorthand notation from (2) to be equivalent to (4) and thus be more consistent with the meaning of the unconstrained template (1). Can somebody shed light on the matter and explain the rationale behind this design decsision?</p>
  
  <p>Some remarks:</p>
  
  <ul>
  <li>afaik, generic lambdas (in C++14) already allow a syntax similar to (1). Hence, consistency dictates that (1) should accept input variables with different types, since generic lambdas do that.</li>
  <li>Stroustrup mentions the classical "iterator pair" in the context of such templates. However, I believe that this is a fairly weak argument since (i) this is just one use-case and (ii) afaik, C++17 introduces (iterator, sentinel) pairs, which forces generic code to use two different types anyway.</li>
  </ul>