<html>
	<head>
		<title>N1696=04-0136, Language Support for Restricted Templates</title>
		<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
		<meta http-equiv="Content-Language" content="en-us">
		<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
	</head>
	<body bgColor="#ffffff">
		<ADDRESS>Document number: N1696=04-0136</ADDRESS>
		<ADDRESS>Programming Language C++, Evolution Working Group</ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>Peter Dimov &lt;<A href="mailto:pdimov@mmltd.net">pdimov@mmltd.net</A>&gt;</ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>September 07, 2004</ADDRESS>
		<h1>Language Support for Restricted Templates</h1>
		<h2>Introduction</h2>
		<P>It has been discovered that in the current language it is possible to 
			selectively enable function template overloads and class template partial 
			specializations based on arbitrary compile-time integral constant expressions. 
			This paper proposes that the library solution, usually named <code>enable_if</code>, 
			should be replaced by core language support in order to improve the syntax and 
			readability of the idiom and remove its outstanding limitations.</P>
		<H2>Motivation</H2>
		<P>The need to enable certain overloads based on arbitrary compile-time conditions 
			is best illustrated by the following well-known example from the standard 
			library:</P>
		<BLOCKQUOTE>
			<P><code>explicit vector(size_type n, const T&amp; value = T(), const Allocator&amp; = 
					Allocator());</code></P>
			<P><code>template &lt;class InputIterator&gt; vector(InputIterator first, InputIterator 
					last, const Allocator&amp; = Allocator());</code></P>
		</BLOCKQUOTE>
		<P>Since input iterator types do not have a distinguished shape that can be used by 
			the template deduction mechanism, we are left with the general second overload 
			that does not place any requirements on its <code>InputIterator</code> parameter, 
			and is sometimes selected for expressions such as</P>
		<BLOCKQUOTE>
			<P><code>vector&lt;int&gt; v( 5, 1 ); // five ints with value 1</code></P>
		</BLOCKQUOTE>
		<P>As a result, the standard library specification explicitly needs to deal with 
			this case in 23.1.1/9 ([lib.sequence.reqmts]/9).</P>
		<P>It is possible to "abuse" the "Substitution Failure Is Not An Error" (SFINAE) 
			principle in order to selectively disable the general overload when 
			InputIterator is an integral type, as follows:</P>
		<BLOCKQUOTE><pre>template&lt;bool Condition, class R = void&gt; struct enable_if {};
template&lt;class R&gt; struct enable_if&lt;true, R&gt; { typedef R type; };

template &lt;class InputIterator&gt; vector(
    InputIterator first, InputIterator last, const Allocator&amp; = Allocator(),
    typename enable_if&lt; !is_integral&lt;InputIterator&gt;::value &gt;::type * = 0
);</pre>
		</BLOCKQUOTE>
		<P>The <code>enable_if</code> utility can also be used in the return type, if there 
			is one:</P>
		<BLOCKQUOTE>
			<P><code>template&lt;class E&gt; typename enable_if&lt; is_expression&lt;E&gt;::value, 
					negate_expression&lt;E&gt; &gt;::type operator! ( E const &amp; e );</code></P>
		</BLOCKQUOTE>
		<P>More information and references on <code>enable_if</code> are provided in the 
			documentation of <code>boost::enable_if</code>, available online at <A href="http://boost.org/libs/utility/enable_if.html">
				http://boost.org/libs/utility/enable_if.html</A>.</P>
		<H2>Proposed Syntax</H2>
		<P>The author proposes that function declarations and partial specialization 
			declarations be extended to support a trailing <code>if( <em>expr</em> )</code>, 
			as in the following examples:</P>
		<BLOCKQUOTE><pre>template &lt;class InputIterator&gt;
    vector( InputIterator first, InputIterator last, const Allocator&amp; = Allocator() )
    if( !is_integral&lt;InputIterator&gt;::value );

template&lt;class E&gt;
    negate_expression&lt;E&gt; operator! ( E const &amp; e )
    if( is_expression&lt;E&gt;::value );

template&lt;class V&gt;
    struct hash&lt;V&gt;
    if( is_integral&lt;V&gt;::value )
{
    size_t operator()(V v) const { return static_cast&lt;size_t&gt;( v ); }
};
</pre>
		</BLOCKQUOTE>
		<p>In addition to "sweetening" the syntax compared to the library-based approach, 
			this change also allows conversion operators to be selectively enabled.</p>
		<H2>Alternative Syntaxes</H2>
		<p>The following alternative syntax has been proposed (by Howard Hinnant):</p>
		<pre>template &lt; class InputIterator: !is_integral&lt;InputIterator&gt;::value &gt;
    vector( InputIterator first, InputIterator last, const Allocator&amp; = Allocator() );
</pre>
		<p>Compared to the proposed syntax, it has the drawback of closely associating the 
			condition with a template parameter. The problems with this approach are 
			twofold. First, the condition may refer to the relationship of several template 
			parameters:</p>
		<pre>template &lt;class A, class B&gt;
    void f( A const &amp; a, B const &amp; b )
    if( is_convertible&lt;A, B&gt;::value || is_convertible&lt;B, A&gt;::value );
</pre>
		<P>Second, the conditional declaration may have no template parameters:</P>
		<pre>template &lt;class T&gt; class X
{
public:

    void f() if( is_integral&lt;T&gt;::value );
};

template &lt;class T, class P&gt; class smart_ptr
{
public:

    smart_ptr( T * p ) if( P::enable_implicit_ctor );
    explicit smart_ptr( T * p ) if( !P::enable_implicit_ctor );
    operator T* () const if( P::enable_conversion_operator );
};
</pre>
		<H2>Concepts</H2>
		<p>This proposal is much less ambitious than the Concepts proposals [<A href="../2003/n1510.pdf">N1510</A>] 
			[<A href="../2003/n1522.pdf">N1522</A>] [<A href="../2003/n1536.pdf">N1536</A>]. 
			It does seem similar at first sight and its obvious applications are, indeed, 
			restricting overly general template parameters to match certain classes of 
			arguments for which the built-in pattern matching cannot be applied. Therefore, 
			the extension presented here will be able to be used as a poor man's 
			substitution of the Concept mechanism, if the latter is not accepted. However, 
			it is not intended to replace, but to complement.</p>
		<P>Concepts express capabilities (the operations a concept supports), and can be 
			used in a function template body to check it statically for errors. They also 
			do not require explicit support from the user in order to match a type. In 
			contrast, conditional declarations express restrictions and can be used to 
			selectively toggle function declarations and partial specializations based on 
			an arbitrary compile-time condition. The two mechanisms are substantially 
			different at their core and each one can solve problems the other cannot. In 
			addition, restricting a template on the relationship of two parameters can 
			avoid specifying a separate templated concept for this purpose whenever 
			appropriate, i.e. when this concept is not essential for the definition and is 
			only being introduced to express a restriction, not a capability.</P>
		<P>It is also worth noting that the proposed extension should be substantially 
			easier to implement, because it is a slight modification of an existing 
			library-based mechanism.</P>
		<H2>Proposed Text</H2>
		<P>This preliminary paper does not propose any specific wording. It is intended to 
			solicit feedback and guidance from the Evolution Working Group as to whether 
			the approach outlined above has potential and should be pursued any further. 
			Future revisions will include proposed changes to ISO/IEC 14882:2003(E).</P>
		<H2>Impact on Existing Code</H2>
		<P>The proposal is a pure extension.</P>
		<ADDRESS>--end</ADDRESS>
	</body>
</html>
