<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.2" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: Perfect forwarding and overload resolution</title>
	<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/</link>
	<description>Boris Kolpackov's blog about software</description>
	<pubDate>Sat, 11 Apr 2026 17:15:17 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>

	<item>
		<title>By: Andrew Nelless</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2054</link>
		<author>Andrew Nelless</author>
		<pubDate>Fri, 01 Jun 2012 13:53:56 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2054</guid>
		<description>Here's some code that demonstrates what I mean:

http://codepad.org/mx41dQZu</description>
		<content:encoded><![CDATA[<p>Here&#8217;s some code that demonstrates what I mean:</p>
<p><a href="http://codepad.org/mx41dQZu" rel="nofollow">http://codepad.org/mx41dQZu</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Nelless</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2053</link>
		<author>Andrew Nelless</author>
		<pubDate>Fri, 01 Jun 2012 13:50:17 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2053</guid>
		<description>Double actually, delete this and the above but not the above of the above ;) I'm right on this.</description>
		<content:encoded><![CDATA[<p>Double actually, delete this and the above but not the above of the above ;) I&#8217;m right on this.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Nelless</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2052</link>
		<author>Andrew Nelless</author>
		<pubDate>Fri, 01 Jun 2012 13:47:58 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2052</guid>
		<description>Actually nevermind, please delete this and the above.</description>
		<content:encoded><![CDATA[<p>Actually nevermind, please delete this and the above.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Nelless</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2051</link>
		<author>Andrew Nelless</author>
		<pubDate>Fri, 01 Jun 2012 13:42:07 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2051</guid>
		<description>Hi Boris, your 'hairy' example is missing "::type" on the end.

I don't quite agree with your solution. First and foremost your template needs to be updated so it is disabled every time a "const Foo&#38;" overload is added. If you're doing that, why not just provide a f(Foo&#38;) overload in the first place?

Convertibility testing is also imperfect. Let's suppose you've only implementing f(int) and a user of your function developers a PrimeNumber class and declares a f(PrimeNumber const&#38;) overload. Let's also suppose this function is in a separate header file and merely forward declares PrimeNumber. Your template will deal with non-const PrimeNumber&#38; lvalue references but, because the only way to provide implicit convertibility to int is via a conversion operator, will silently fail the is_convertible test because the full definition of the PrimeNumber class isn't  unavailable. 

The result your template is still selected over the const&#38; variant and your user is going to get unexpected linker errors or inconsistent behaviour.</description>
		<content:encoded><![CDATA[<p>Hi Boris, your &#8216;hairy&#8217; example is missing &#8220;::type&#8221; on the end.</p>
<p>I don&#8217;t quite agree with your solution. First and foremost your template needs to be updated so it is disabled every time a &#8220;const Foo&amp;&#8221; overload is added. If you&#8217;re doing that, why not just provide a f(Foo&amp;) overload in the first place?</p>
<p>Convertibility testing is also imperfect. Let&#8217;s suppose you&#8217;ve only implementing f(int) and a user of your function developers a PrimeNumber class and declares a f(PrimeNumber const&amp;) overload. Let&#8217;s also suppose this function is in a separate header file and merely forward declares PrimeNumber. Your template will deal with non-const PrimeNumber&amp; lvalue references but, because the only way to provide implicit convertibility to int is via a conversion operator, will silently fail the is_convertible test because the full definition of the PrimeNumber class isn&#8217;t  unavailable. </p>
<p>The result your template is still selected over the const&amp; variant and your user is going to get unexpected linker errors or inconsistent behaviour.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Joe</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2050</link>
		<author>Joe</author>
		<pubDate>Fri, 01 Jun 2012 12:57:20 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2050</guid>
		<description>I wasn't trying to resolve the specific example.  I was only trying to demonstrate that the same problem in the example exists if you overload with an lvalue ref template and, to a lesser extent, a non-reference template.  With the point being that this particular trap is not rvalue ref/perfect forwarding specific.</description>
		<content:encoded><![CDATA[<p>I wasn&#8217;t trying to resolve the specific example.  I was only trying to demonstrate that the same problem in the example exists if you overload with an lvalue ref template and, to a lesser extent, a non-reference template.  With the point being that this particular trap is not rvalue ref/perfect forwarding specific.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2049</link>
		<author>Boris Kolpackov</author>
		<pubDate>Fri, 01 Jun 2012 06:19:03 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2049</guid>
		<description>Joe, Andrew, I agree there are different ways to resolve this issue. The approach I suggested is general enough that it can be applied to any set of overloaded functions while your approaches could be a better fit for this particular example.</description>
		<content:encoded><![CDATA[<p>Joe, Andrew, I agree there are different ways to resolve this issue. The approach I suggested is general enough that it can be applied to any set of overloaded functions while your approaches could be a better fit for this particular example.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Andrew Nelless</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2047</link>
		<author>Andrew Nelless</author>
		<pubDate>Fri, 01 Jun 2012 00:53:40 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2047</guid>
		<description>You could have also created a template for static char arrays.

template  
void f (char const (&#38;arr)[N]) { f(std::string((char const*) arr, N)); }

Doing this will handle all the char array cases and (almost insignificantly) speed up the std::string construction. If your array reference contains binary data (a null char) this would actually be the safer option anyway (I think).

Personally I don't feel the binding of f(s) to [T = std::string&#38;] instead of to (const std::string&#38;) is a bad thing either. Your perfect forwarding function could forward to a function capable of receiving a mutable reference. The alternative would be to force binding to const&#38; over T&#38;&#38; and screw you over when you wanted to do just that.</description>
		<content:encoded><![CDATA[<p>You could have also created a template for static char arrays.</p>
<p>template<br />
void f (char const (&amp;arr)[N]) { f(std::string((char const*) arr, N)); }</p>
<p>Doing this will handle all the char array cases and (almost insignificantly) speed up the std::string construction. If your array reference contains binary data (a null char) this would actually be the safer option anyway (I think).</p>
<p>Personally I don&#8217;t feel the binding of f(s) to [T = std::string&amp;] instead of to (const std::string&amp;) is a bad thing either. Your perfect forwarding function could forward to a function capable of receiving a mutable reference. The alternative would be to force binding to const&amp; over T&amp;&amp; and screw you over when you wanted to do just that.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Joe</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2046</link>
		<author>Joe</author>
		<pubDate>Thu, 31 May 2012 21:21:31 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2046</guid>
		<description>I am not sure this is a fair criticism of rvalue refs or perfect forwarding.

I think you would run into the exact same issues if you used a simple rvalue ref

template 
void f (T &#38; x)
{
  g (x);
}

if instead you use

template 
void f (T x)
{
  g (x);
}

Then f(s) will use the expected specialization, but f("bbb") will use the template.

The general lesson I've learned in the past is that overloading templates and non-templates that vary in cv qualifications or reference is asking for trouble.  If a function signature doesn't match the argument type exactly, it's likely the template will be chosen.</description>
		<content:encoded><![CDATA[<p>I am not sure this is a fair criticism of rvalue refs or perfect forwarding.</p>
<p>I think you would run into the exact same issues if you used a simple rvalue ref</p>
<p>template<br />
void f (T &amp; x)<br />
{<br />
  g (x);<br />
}</p>
<p>if instead you use</p>
<p>template<br />
void f (T x)<br />
{<br />
  g (x);<br />
}</p>
<p>Then f(s) will use the expected specialization, but f(&#8221;bbb&#8221;) will use the template.</p>
<p>The general lesson I&#8217;ve learned in the past is that overloading templates and non-templates that vary in cv qualifications or reference is asking for trouble.  If a function signature doesn&#8217;t match the argument type exactly, it&#8217;s likely the template will be chosen.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: sap</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2042</link>
		<author>sap</author>
		<pubDate>Wed, 30 May 2012 22:04:20 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2042</guid>
		<description>oops the problem was indeed the missing const, not it works as you say.
great stuff.</description>
		<content:encoded><![CDATA[<p>oops the problem was indeed the missing const, not it works as you say.<br />
great stuff.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Boris Kolpackov</title>
		<link>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2041</link>
		<author>Boris Kolpackov</author>
		<pubDate>Wed, 30 May 2012 18:44:50 +0000</pubDate>
		<guid>https://codesynthesis.com/~boris/blog//2012/05/30/perfect-forwarding-and-overload-resolution/#comment-2041</guid>
		<description>Yes, without the enable_if addition, f(s) will be resolved to the forwarding function. I tested this with GCC 4.7 and now confirmed with Clang 3.0.

Note also that the non-template function in the post has the void f (const string&#38;) signature, not void f (string&#38;) as in your comment (that would certainly explain the difference in behavior). The other possibility is that VC11 implements v2.1 of the rvalue reference specification while GCC and Clang implement v3, which is what's in the standard.</description>
		<content:encoded><![CDATA[<p>Yes, without the enable_if addition, f(s) will be resolved to the forwarding function. I tested this with GCC 4.7 and now confirmed with Clang 3.0.</p>
<p>Note also that the non-template function in the post has the void f (const string&amp;) signature, not void f (string&amp;) as in your comment (that would certainly explain the difference in behavior). The other possibility is that VC11 implements v2.1 of the rvalue reference specification while GCC and Clang implement v3, which is what&#8217;s in the standard.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
