<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
  <style type="text/css">

.comment { color: #999999; font-style: italic; }
.pre { color: #000099; }
.string { color: #009900; }
.char { color: #009900; }
.float { color: #996600; }
.int { color: #999900; }
.bool { color: #000000; font-weight: bold; }
.type { color: #FF6633; }
.flow { color: #FF0000; }
.keyword { color: #990000; }
.operator { color: #663300; font-weight: bold; }
.operator { color: #663300; font-weight: bold; }
pre.code {
    border: 2px solid #666;
    background-color: #F4F4F4;
    padding-left: 10px;
    padding-top: 0px;
}
mycode {
    border: 2px solid #d0d0d0;
    background-color: LightYellow;
    padding: 2px;
    padding-left: 10px;
    display:table;
    white-space:pre;
    margin:2px;
    margin-bottom:10px;
}
dt {
    font-weight: bold;
}
.ins {
    background-color:#A0FFA0;
}
.del {
    background-color:#FFA0A0;
    text-decoration:line-through
}    
</style>

<title>Template parameter deduction for constructors (Rev. 2)</title>
</head>

<body>
<p>P0091R0<br>
Revision of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4471.html">N4471</a><br>
2015-09-24<br>
Mike Spertus, Symantec<br>
<a href="mailto:mike_spertus@symantec.com">mike_spertus@symantec.com</a><br>
Richard Smith<br>
<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a><br>
</p>

<h1>Template parameter deduction for constructors (Rev. 3)</h1> 
	<h2>Summary</h2>
    <p> This paper proposes extending template parameter deduction for functions
		to constructors of template classes and incorporates feedback from the EWG review of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4471.html">N4471</a>.</p>
<p>Currently, if we want to construct template classes, we need to specify the template parameters. 
	For example, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4498.html">N4498</a> on Variadic Lock Guards
	gives an example of acquiring a <tt>lock_guard</tt> on two mutexes inside an <tt>operator=</tt> to properly lock both the
	source and destination of the assignment. Expanding typedefs, the locks are acquired by the following statement
	(See the paper for details and rationale).
	<mycode>std::lock_guard&lt;std::shared_timed_mutex, std::shared_lock&lt;std::shared_timed_mutex&gt;&gt; lck(mut_, r1);</mycode>
	Having to specify the template parameters adds nothing but complexity! If constructors could deduce their template
	parameters "like we expect from other functions and methods," then the following vastly simpler and more intuitive code could 
	have been used instead.
	<mycode>auto lock = std::lock_guard(mut_, r1);</mycode>
	Lest one think that this problem could have been avoided if only <tt>lock_guard</tt> had a &ldquo;make function,&rdquo;
	<tt>lock_guard</tt> is not moveable and therefore cannot have a make function. Indeed, LEWG explicitly declined to
	make it moveable before advancing the paper to LWG. As we will see below, even for moveable class, &ldquo;make functions&rdquo;
	have their own problems.
	</p>
	<p>The sections below first spell out the problem in more detail and then makes precise what &ldquo;like we expect from other
	functions and methods&rdquo; means in this context.</p>

	<h2>The problem</h2>
	
	<p>To simplify the examples below, suppose the following definitions are in place.

<mycode>vector&lt;int&gt; vi1 = { 0, 1, 1, 2, 3, 5, 8 };
vector&lt;int&gt; vi2;
template&lt;class Func&gt;
std::mutex m;
unique_lock&lt;std::mutex&gt; ul(m, std::defer_lock);
class Foo() { 
public: 
    Foo(Func f) : func(f) {} 
    void operator()(int i) { 
      os &lt;&lt; "Calling with " &lt;&lt; i &lt;&lt; endl;
      f(i); 
    } 
private: 
    Func func; 
    mutex mtx;
};</mycode>
<p>In the current standard, the following objects would be constructed as shown</p>
<mycode>pair&lt;int, double&gt; p(2, 4.5);
auto t = make_tuple(4, 3, 2.5);
copy_n(vi1, 3, back_inserter(vi2));
<span class="comment">// Virtually impossible to pass a lambda to a template class' constructor</span>
for_each(vi2.begin(), vi2.end(), Foo&lt;<span class="comment">???</span>&gt;([&amp;](int i) { <span class="comment">...</span>}));
lock_guard&lt;std::mutex&gt; lck(foo.mtx);
lock_guard&lt;std::mutex, std::unique_lock&lt;std::mutex&gt;&gt; lck2(foo.mtx, ul); <span class="comment">// Notation from N4470</span>
auto hasher = [](X const &amp; x) -&gt; size_t { <span class="comment">/* ... */</span> };
unordered_map&lt;X, int, decltype(hasher)&gt; ximap(10, hasher);
</mycode>

There are several problems with the above code:
</p><ul>

<li>Creating &ldquo;make functions&rdquo; like <tt>make_tuple</tt> is confusing,
artificial, extra boilerplate, and inconsistent with how non-template classes are constructed.</li>

<li>Since the standard library doesn't follow any consistent convention for
make functions, users have to scurry through documentation to find they need to
use <tt>make_tuple</tt> for <tt>tuple</tt>s
and <tt>back_inserter</tt> for <tt>back_insert_iterator</tt>s. Of course their own
template classes might not be as consistent or thoroughly-documented as the standard.</li>

<li>Specifying template parameters as in <tt>pair&lt;int, double&gt;(2, 4.5)</tt>
should be unnecessary since they can be inferred from the type of the arguments, as is
usual with template functions (this is the reason the standard provides make functions
for many template classes in the first place!).
</li>
	<li>A make function may do more than just deduce constructor template parameters. Unless
	a detailed study of the documentation is made (which usually only happens when debugging
	weird unexpected behavior...), subtle changes in semantics may occur. Committee members
	and other C++ experts are invited to see if they can tell which of the above make functions
	simply do the &ldquo;obvious&rdquo; deduction of template parameters.</li>
<li>If we don't have a make function, we may not be able to
create class objects at all as indicated by the <tt><span class="comment">???</span></tt>
in the code above.</li>
<li>Make functions can't be used with classes that aren't movable like <tt>std::lock_guard</tt>.</li>
<li>The useful technique of replacing a large function with a class by 
organizing its code into methods to reduce cyclomatic complexity can't 
be used for template functions</li>
</ul>

If we allowed the compiler to deduce the template parameters for constructors of
template classes, we could replace the above with:

<mycode>pair p(2, 4.5);
tuple t(4, 3, 2.5);
copy_n(vi1, 3, back_insert_iterator(vi2));
for_each(vi.begin(), vi.end(), Foo([&amp;](int i) { <span class="comment">...</span>})); <span class="comment">// Now easy instead of virtually impossible</span>
auto lck = lock_guard(foo.mtx);
lock_guard lck2(foo.mtx, ul);
unordered_map&lt;X, int&gt; ximap(10, [](X const &amp; x) -&gt; size_t { <span class="comment">/* ... */</span> });
</mycode>

We believe this is more consistent and simpler for both users and writers of
template classes, especially for user-defined classes that might
not have carefully designed and documented make functions like <tt>pair</tt>,
<tt>tuple</tt>, and <tt>back_insert_iterator</tt>.
<h2>The Solution</h2>
<p>We propose two techniques
	<ul><li><a href="#adoec">Auto-deduction of existing constructors</a></li>
	<li><a href="#cff">Canonical factory functions</a></li></ul>
	These techniques work well together as will be explained below. They
	can also be adopted separately (E.g., as a result of the discussion on <a href="#CodeCompatibility">Code Compatibility</a> below).</p>
<h3><a name="adoec"/>Auto-deduction of existing constructors</h3>
<p>We propose to allow a template name referring to a class template as a
simple-type-specifier in two contexts:
</p><ul>

  <li>Functional-notation simple type conversions ([expr.type.conv], and</li>
  <li>Simple-declarations of the form
      "<i>decl-specifier-seq id-expression initializer</i>".</li>
</ul>
<p>
In the case of
a function-notation type conversion (e.g., "<tt>tuple(1, 2.0, false)</tt>") or
a direct parenthesized or braced initialization,
the initialization is resolved as follows.
First, constructors and constructor templates declared in the named template
are enumerated.  Let Ci be such a constructor or constructor template;
together they form an overload set.  A parallel overload set <i>F</i> of
function templates is then created as follows:

For each Ci a function template is constructed with template parameters that
include both those of the named class template and if Ci is a constructor
template, those of that template (default arguments are included too) --
the function parameters are the constructor parameters, and the return type
is <tt>void</tt>

Deduction and overload resolution is then performed for a synthesized call
to <i>F</i> with the parenthesized or braced expressions used as arguments.
If that call doesn't yield a "best viable function", the program is ill-formed.
Otherwise, the template name is treated as the class-name that is obtained
from the named class template with the deduced arguments corresponding to that
template's parameters.
</p>
<p>
Let's look at an example:
<mycode>template&lt;typename T&gt; struct S {
  template&lt;typename U&gt; struct N {
    N(T);
    N(T, U);
    template&lt;typename V&gt; N(V, U);
  };
};

S&lt;int&gt;::N x{2.0, 1};
</mycode>

In this example, "<tt>S&lt;int&gt;::N</tt>" in the declaration of <tt>x</tt>
is missing template arguments, so the approach above kicks in.
Template arguments can only be left out this way from the "type" of the
declaration, but not from any name qualifiers used in naming the template;
i.e., we couldn't replace "<tt>S&lt;int&gt;::N</tt>" by just "<tt>S::N</tt>"
using some sort of additional level of deduction.
To deduce the initialized type, the compiler now creates an overload set as
follows:

<mycode>
    template&lt;typename U&gt; void <i>F</i>(S&lt;int&gt;::N&lt;U&gt; const&amp;);
    template&lt;typename U&gt; void <i>F</i>(S&lt;int&gt;::N&lt;U&gt; &amp;&amp;);
    template&lt;typename U&gt; void <i>F</i>(int);
    template&lt;typename U&gt; void <i>F</i>(int, U);
    template&lt;typename U, typename V&gt; void <i>F</i>(V, U);
</mycode>

(The first two candidates correspond to the implicitly-declared copy and move
contructors. Note that template parameter <tt>T</tt> is already known to
be <tt>int</tt> and is not a template parameter in the synthesized overload
set.)

Then the compiler performs overload resolution for a call "<tt><i>F</i>(2.0, 1)</tt>" 
which in this case finds a unique best candidate in the last synthesized function
with <tt>U = int</tt> and <tt>V = double</tt>.  The initialization
is therefore treated as "<tt>S&lt;int&gt;::N&lt;int&gt; x{2.0, 1};</tt>"
</p>



<p>
Note that after the deduction process described above the initialization may
still end up being ill-formed.  For example, a selected constructor might be
inaccessible or deleted, or the selected template instance might have been
specialized or partially specialized in such a way that the candidate
constructors will not match the initializer.
</p>

The case of a simple-declaration with copy-initialization syntax is treated
similarly to the approach described above, except that explicit constructors
and constructor templates are ignored, and the initializer expression is
used as the single call argument during the deduction process.

<h3><a name="cff"/>Canonical factory functions</h3>
	<p>While the above procedure generates many useful deducible constructors,
		some constructors that we would like to be deducible are not. For example, 
		one could imaging a function <tt>make_vector</tt>
    defined as follows:</p><mycode>template&lt;typename Iter&gt;
vector&lt;Iter::value_type&gt; make_vec(Iter b, Iter e) {
  return vector&lt;Iter::value_type&gt;(b, e);
}
    </mycode>
<p>Although there is no constructor in <tt>vector</tt> from which we can deduce the type
    of the vector from two iterators, one would like to be able to deduce the type of
	the vector from the value type of the two iterators.
		For example, some implementations of the STL define their <tt>value_type</tt>
<tt>typedef</tt> as follows
<mycode>template&lt;typename T, typename Alloc=std::allocator&lt;T&gt;&gt;
struct vector {
  struct iterator {
    typedef T value_type;
    <span class="comment">/* ... */</span>
  };
  typedef iterator::value_type value_type;
  <span class="comment">/* ... */</span>
};
</mycode>
The detour through <tt>vector&lt;T&gt;::iterator</tt> keeps us from
deducing that <tt>T</tt> is <tt>char</tt> in a constructor call like <tt>vector(5, 'c')</tt>.
We would certainly like constructors like that to work.</p>

<p>We suggest a notation to allow constructors
to specify their template parameters by either explicitly declaring the signatures for 
	any further needed constructor deductions outside the class 
	<mycode>template&lt;typename T, typename Alloc = std::allocator&lt;T&gt;&gt; struct vector {
  <span class="comment">/* ... */</span>
};
template&lt;typename Iter&gt; vector(Iter b, Iter e) -&gt; vector&lt;typename iterator_traits&lt;Iter&gt;::value_type&gt;
</mycode>
 <p>In effect, this allows any pure factory function to be specified with any deduction rules that are specifiable
	by any function with a standard first-class name and no boilerplate code in the body. It also allows us
	to suppress a standard deduction from the above process via &ldquo;<tt>= delete;&rdquo;</tt></p>   
	<p>Alternatively, we could use &ldquo;declaration notation&rdquo;</p>
<mycode>template&lt;typename Iter&gt; vector&lt;typename iterator_traits&lt;Iter&gt;::value_type&gt; vector(Iter b, Iter e); 
template&lt;typename Iter&gt; auto vector(Iter b, Iter e) -&gt; vector&lt;typename iterator_traits&lt;Iter&gt;::value_type&gt;; 
</mycode>

	<p>Note that it is only necessary to declare canonical factory functions.
 Giving a definition is not allowed as they just construct their return 
type from their arguments according
to normal rules. This restriction makes it instantly visible that any use of a constructor as a factory
	simply constructs the class and does not have any obscure semantics.</p>
<h3>A note on injected class names</h3>
<p>The focus on this paper is on simplifying the interface of a
	class for its clients. Within a class, one may need to explicitly specify the parameters as 
	before due to the injected class name:</p>
<mycode>template&lt;typename T&gt; struct X {
  template&lt;typename Iter&gt;
  X(Iter b, Iter e) { <span class="comment">/* ... */</span> }
	
  template&lt;typename Iter&gt;
  auto foo(Iter b, Iter e) { 
     return X(b, e); <span class="comment">// X&lt;U&gt; to avoid breaking change</span>
  }
	
  template&lt;typename Iter&gt;
  auto bar(Iter b, Iter e) { 
     return X&lt;Iter::value_type&gt;(b, e); <span class="comment">// Must specify what we want</span>
  }
};
</mycode>
<h3><a name="CodeCompatibility"/>Code compatibility</h3>
While we cannot say whether it is a problem in practice, we should point out a 
scenario where auto-deduction can break compatibility. 
	
<p>Suppose I produce a library and I'm under license to preserve source compatibility across all 1.x upgrades, and I have this class template in version 1.0:</p>

<mycode>template<typename T> struct X {
  X(T);
};</mycode>

	<p>... and in version 1.1 I rewrite it as this:</p>

<mycode>template<typename T> struct X {
  struct iterator { typedef T type; };
  X(typename iterator::type);
};</mycode>

<p>If one of my users upgrades to C++17, with this change in the language, I am no longer complying with the terms of my licensing. Likewise, if this language change happens between me releasing 1.0 and 1.1, I can no longer release version 1.1 because it might break some of my existing customers.</p>

<p>The point is: current code does not express any intent about whether class template parameters are deducible, based on whether they use the version 1.0 code or the version 1.1 code. But this change makes that implicit property into part of the de facto interface of the code.</p>
<p>So why include auto-deduction at all in this proposal as canonical factory functions could
be used to make explicit all of the auto-deduced constructors? Basically, having to manually specify what is obviously expected has an insidious cost as any (honest) Java programmer can tell you so we would like to discuss with the committee whether this will
be an actual problem in practice before jettisoning a useful feature and make programmers manually insert the &ldquo;obvious&rdquo; canonical factory functions for all of their existing classes.</p>
</body></html>