Fri Nov 22 00:27:24 2024
EVENTS
 FREE
SOFTWARE
INSTITUTE

POLITICS
JOBS
MEMBERS'
CORNER

MAILING
LIST

NYLXS Mailing Lists and Archives
NYLXS Members have a lot to say and share but we don't keep many secrets. Join the Hangout Mailing List and say your peice.

DATE 2011-04-01

HANGOUT

2024-11-22 | 2024-10-22 | 2024-09-22 | 2024-08-22 | 2024-07-22 | 2024-06-22 | 2024-05-22 | 2024-04-22 | 2024-03-22 | 2024-02-22 | 2024-01-22 | 2023-12-22 | 2023-11-22 | 2023-10-22 | 2023-09-22 | 2023-08-22 | 2023-07-22 | 2023-06-22 | 2023-05-22 | 2023-04-22 | 2023-03-22 | 2023-02-22 | 2023-01-22 | 2022-12-22 | 2022-11-22 | 2022-10-22 | 2022-09-22 | 2022-08-22 | 2022-07-22 | 2022-06-22 | 2022-05-22 | 2022-04-22 | 2022-03-22 | 2022-02-22 | 2022-01-22 | 2021-12-22 | 2021-11-22 | 2021-10-22 | 2021-09-22 | 2021-08-22 | 2021-07-22 | 2021-06-22 | 2021-05-22 | 2021-04-22 | 2021-03-22 | 2021-02-22 | 2021-01-22 | 2020-12-22 | 2020-11-22 | 2020-10-22 | 2020-09-22 | 2020-08-22 | 2020-07-22 | 2020-06-22 | 2020-05-22 | 2020-04-22 | 2020-03-22 | 2020-02-22 | 2020-01-22 | 2019-12-22 | 2019-11-22 | 2019-10-22 | 2019-09-22 | 2019-08-22 | 2019-07-22 | 2019-06-22 | 2019-05-22 | 2019-04-22 | 2019-03-22 | 2019-02-22 | 2019-01-22 | 2018-12-22 | 2018-11-22 | 2018-10-22 | 2018-09-22 | 2018-08-22 | 2018-07-22 | 2018-06-22 | 2018-05-22 | 2018-04-22 | 2018-03-22 | 2018-02-22 | 2018-01-22 | 2017-12-22 | 2017-11-22 | 2017-10-22 | 2017-09-22 | 2017-08-22 | 2017-07-22 | 2017-06-22 | 2017-05-22 | 2017-04-22 | 2017-03-22 | 2017-02-22 | 2017-01-22 | 2016-12-22 | 2016-11-22 | 2016-10-22 | 2016-09-22 | 2016-08-22 | 2016-07-22 | 2016-06-22 | 2016-05-22 | 2016-04-22 | 2016-03-22 | 2016-02-22 | 2016-01-22 | 2015-12-22 | 2015-11-22 | 2015-10-22 | 2015-09-22 | 2015-08-22 | 2015-07-22 | 2015-06-22 | 2015-05-22 | 2015-04-22 | 2015-03-22 | 2015-02-22 | 2015-01-22 | 2014-12-22 | 2014-11-22 | 2014-10-22 | 2014-09-22 | 2014-08-22 | 2014-07-22 | 2014-06-22 | 2014-05-22 | 2014-04-22 | 2014-03-22 | 2014-02-22 | 2014-01-22 | 2013-12-22 | 2013-11-22 | 2013-10-22 | 2013-09-22 | 2013-08-22 | 2013-07-22 | 2013-06-22 | 2013-05-22 | 2013-04-22 | 2013-03-22 | 2013-02-22 | 2013-01-22 | 2012-12-22 | 2012-11-22 | 2012-10-22 | 2012-09-22 | 2012-08-22 | 2012-07-22 | 2012-06-22 | 2012-05-22 | 2012-04-22 | 2012-03-22 | 2012-02-22 | 2012-01-22 | 2011-12-22 | 2011-11-22 | 2011-10-22 | 2011-09-22 | 2011-08-22 | 2011-07-22 | 2011-06-22 | 2011-05-22 | 2011-04-22 | 2011-03-22 | 2011-02-22 | 2011-01-22 | 2010-12-22 | 2010-11-22 | 2010-10-22 | 2010-09-22 | 2010-08-22 | 2010-07-22 | 2010-06-22 | 2010-05-22 | 2010-04-22 | 2010-03-22 | 2010-02-22 | 2010-01-22 | 2009-12-22 | 2009-11-22 | 2009-10-22 | 2009-09-22 | 2009-08-22 | 2009-07-22 | 2009-06-22 | 2009-05-22 | 2009-04-22 | 2009-03-22 | 2009-02-22 | 2009-01-22 | 2008-12-22 | 2008-11-22 | 2008-10-22 | 2008-09-22 | 2008-08-22 | 2008-07-22 | 2008-06-22 | 2008-05-22 | 2008-04-22 | 2008-03-22 | 2008-02-22 | 2008-01-22 | 2007-12-22 | 2007-11-22 | 2007-10-22 | 2007-09-22 | 2007-08-22 | 2007-07-22 | 2007-06-22 | 2007-05-22 | 2007-04-22 | 2007-03-22 | 2007-02-22 | 2007-01-22 | 2006-12-22 | 2006-11-22 | 2006-10-22 | 2006-09-22 | 2006-08-22 | 2006-07-22 | 2006-06-22 | 2006-05-22 | 2006-04-22 | 2006-03-22 | 2006-02-22 | 2006-01-22 | 2005-12-22 | 2005-11-22 | 2005-10-22 | 2005-09-22 | 2005-08-22 | 2005-07-22 | 2005-06-22 | 2005-05-22 | 2005-04-22 | 2005-03-22 | 2005-02-22 | 2005-01-22 | 2004-12-22 | 2004-11-22 | 2004-10-22 | 2004-09-22 | 2004-08-22 | 2004-07-22 | 2004-06-22 | 2004-05-22 | 2004-04-22 | 2004-03-22 | 2004-02-22 | 2004-01-22 | 2003-12-22 | 2003-11-22 | 2003-10-22 | 2003-09-22 | 2003-08-22 | 2003-07-22 | 2003-06-22 | 2003-05-22 | 2003-04-22 | 2003-03-22 | 2003-02-22 | 2003-01-22 | 2002-12-22 | 2002-11-22 | 2002-10-22 | 2002-09-22 | 2002-08-22 | 2002-07-22 | 2002-06-22 | 2002-05-22 | 2002-04-22 | 2002-03-22 | 2002-02-22 | 2002-01-22 | 2001-12-22 | 2001-11-22 | 2001-10-22 | 2001-09-22 | 2001-08-22 | 2001-07-22 | 2001-06-22 | 2001-05-22 | 2001-04-22 | 2001-03-22 | 2001-02-22 | 2001-01-22 | 2000-12-22 | 2000-11-22 | 2000-10-22 | 2000-09-22 | 2000-08-22 | 2000-07-22 | 2000-06-22 | 2000-05-22 | 2000-04-22 | 2000-03-22 | 2000-02-22 | 2000-01-22 | 1999-12-22

Key: Value:

Key: Value:

MESSAGE
DATE 2011-04-12
FROM Ruben Safir
SUBJECT Subject: [NYLXS - HANGOUT] C++ Workshop Template, claass and function specialization
http://www.gotw.ca/publications/mill17.htm

Why Not Specialize Function Templates?

This article appeared in C/C++ Users Journal, 19(7), July 2001.



While the title of this article is a question, it could also be made
into a statement: this article is about when and why not to specialize
templates.
The Important Difference: Overloading vs. Specialization

It's important to make sure we have the terms down pat, so here's a
quick review.

In C++, there are class templates and function templates. These two
kinds of templates don't work in exactly the same ways, and the most
obvious difference is in overloading: Plain old C++ classes don't
overload, so class templates don't overload either. On the other hand,
plain old C++ functions having the same name do overload, and so
function templates are allowed to overload too. This is pretty natural.
What we have so far is summarized in Example 1:

// Example 1: Class vs. function template, and overloading
//

// A class template
template class X { /*...*/ }; // (a)

// A function template with two overloads
template void f( T ); // (b)
template void f( int, T, double ); // (c)

These unspecialized templates are also called the underlying base
templates.

Further, base templates can be specialized. This is where class
templates and function templates diverge further, in ways that will
become important later in this article. A class template can be
partially specialized and/or fully specialized.[1] A function template
can only be fully specialized, but because function templates can
overload we can get nearly the same effect via overloading that we could
have got via partial specialization. The following code illustrates
these differences:

// Example 1, continued: Specializing templates
//

// A partial specialization of (a) for pointer types
template class X { /*...*/ };

// A full specialization of (a) for int
template<> class X { /*...*/ };

// A separate base template that overloads (b) and (c)
// -- NOT a partial specialization of (b), because
// there's no such thing as a partial specialization
// of a function template!
template void f( T* ); // (d)

// A full specialization of (b) for int
template<> void f( int ); // (e)

// A plain old function that happens to overload with
// (b), (c), and (d) -- but not (e), which we'll
// discuss in a moment
void f( double ); // (f)

Finally, let's focus on function templates only and consider the
overloading rules to see which ones get called in different situations.
The rules are pretty simple, at least at a high level, and can be
expressed as a classic two-class system:

Nontemplate functions are first-class citizens. A plain old
nontemplate function that matches the parameter types as well as any
function template will be selected over an otherwise-just-as-good
function template.

If there are no first-class citizens to choose from that are at
least as good, then function base templates as the second-class citizens
get consulted next. Which function base template gets selected depends
on which matches best and is the "most specialized" (important note:
this use of "specialized" oddly enough has nothing to do with template
specializations; it's just an unfortunate colloquialism) according to a
set of fairly arcane rules:

If it's clear that there's one "most specialized" function base
template, that one gets used. If that base template happens to be
specialized for the types being used, the specialization will get used,
otherwise the base template instantiated with the correct types will be
used.

Else if there's a tie for the "most specialized" function base
template, the call is ambiguous because the compiler can't decide which
is a better match. The programmer will have to do something to qualify
the call and say which one is wanted.

Else if there's no function base template that can be made to
match, the call is bad and the programmer will have to fix the code.

Putting these rules together, here's a sample of what we get:

// Example 1, continued: Overload resolution
//
bool b;
int i;
double d;

f( b ); // calls (b) with T = bool
f( i, 42, d ); // calls (c) with T = int
f( &i ); // calls (d) with T = int
f( i ); // calls (e)
f( d ); // calls (f)

So far I've deliberately chosen simpler cases, because here's where we
step off into the deep end of the pool.
Why Not Specialize: The Dimov/Abrahams Example

Consider the following code:

// Example 2: Explicit specialization
//
template // (a) a base template
void f( T );

template // (b) a second base template, overloads (a)
void f( T* ); // (function templates can't be partially
// specialized; they overload instead)

template<> // (c) explicit specialization of (b)
void f<>(int*);

// ...

int *p;
f( p ); // calls (c)

The result for the last line in Example 2 is just what you'd expect. The
question of the day, however, is why you expected it. If you expected it
for the wrong reason, you will be very surprised by what comes next.
After all, "So what," someone might say, "I wrote a specialization for a
pointer to int, so obviously that's what should be called" - and that's
exactly the wrong reason.

Consider now the following code, put in this form by Peter Dimov and
Dave Abrahams:

// Example 3: The Dimov/Abrahams Example
//
template // (a) same old base template as before
void f( T );

template<> // (c) explicit specialization, this time of (a)
void f<>(int*);

template // (b) a second base template, overloads (a)
void f( T* );

// ...

int *p;
f( p ); // calls (b)! overload resolution ignores
// specializations and operates on the base
// function templates only

If this surprises you, you're not alone; it has surprised a lot of
experts in its time. The key to understanding this is simple, and here
it is: Specializations don't overload.

Only the base templates overload (along with nontemplate functions, of
course). Consider again the salient part from the summary I gave above
of the overload resolution rules, this time with specific words
highlighted:

…

If there are no first-class citizens to choose from that are at
least as good, then function base templates as the second-class citizens
get consulted next. Which function base template gets selected depends
on which matches best and is the "most specialized" […] according to
a set of fairly arcane rules:

If it's clear that there's one "most specialized" function base
template, that one gets used. If that base template happens to be
specialized for the types being used, the specialization will get used,
otherwise the base template instantiated with the correct types will be
used.

... etc.

Overload resolution only selects a base template (or a nontemplate
function, if one is available). Only after it's been decided which base
template is going to be selected, and that choice is locked in, will the
compiler look around to see if there happens to be a suitable
specialization of that template available, and if so that specialization
will get used.
Important Morals

If you're like me, the first time you see this you'll ask the question:
"Hmm. But it seems to me that I went and specifically wrote a
specialization for the case when the parameter is an int*, and it is an
int* which is an exact match, so shouldn't my specialization always get
used?" That, alas, is a mistake: If you want to be sure it will always
be used in the case of exact match, that's what a plain old function is
for -- so just make it a function instead of a specialization.

The rationale for why specializations don't participate in overloading
is simple, once explained, because the surprise factor is exactly the
reverse: The standards committee felt it would be surprising that, just
because you happened to write a specialization for a particular
template, that it would in any way change which template gets used.
Under that rationale, and since we already have a way of making sure our
version gets used if that's what we want (we just make it a function,
not a specialization), we can understand more clearly why
specializations don't affect which template gets selected.

Moral #1: If you want to customize a function base template and want
that customization to participate in overload resolution (or, to always
be used in the case of exact match), make it a plain old function, not a
specialization. And, if you do provide overloads, avoid also providing
specializations.

But what if you're the one who's writing, not just using, a function
template? Can you do better and avoid this (and other) problem(s) up
front, for yourself and for your users? Indeed you can:

Moral #2: If you're writing a function base template, prefer to
write it as a single function template that should never be specialized
or overloaded, and then implement the function template entirely as a
simple handoff to a class template containing a static function with the
same signature. Everyone can specialize that -- both fully and
partially, and without affecting the results of overload resolution.

// Example 4: Illustrating Moral #2
//
template
struct FImpl;

template
void f( T t ) { FImpl::f( t ); } // users, don't touch this!

template
struct FImpl
{
static void f( T t ); // users, go ahead and specialize this
};
Summary

It's okay to overload function templates. Overload resolution considers
all base templates equally and so it works as you would naturally expect
from your experience with normal C++ function overloading: Whatever
templates are visible are considered for overload resolution, and the
compiler simply picks the best match.

It's a lot less intuitive to specialize function templates. For one
thing, you can't partially specialize them -- pretty much just because
the language says you can't.[2] For another thing, function template
specializations don't overload. This means that any specializations you
write will not affect which template gets used, which runs counter to
what most people would intuitively expect. After all, if you had written
a nontemplate function with the identical signature instead of a
function template specialization, the nontemplate function would always
be selected because it's always considered to be a better match than a
template.

If you're writing a function template, prefer to write it as a single
function template that should never be specialized or overloaded, and
implement the function template entirely in terms of a class template.
This is the proverbial level of indirection that steers you well clear
of the limitations and dark corners of function templates. This way,
programmers using your template will be able to partially specialize and
explicitly specialize the class template to their heart's content
without affecting the expected operation of the function template. This
avoids both the limitation that function templates can't be partially
specialized, and the sometimes surprising effect that function template
specializations don't overload. Problem solved.

If you're using someone else's plain old function template (one that's
not implemented in terms of a class template as suggested above), and
you want to write your own special-case version that should participate
in overloading, don't make it a specialization; just make it an
overloaded function with the same signature.
Acknowledgments

Thanks to Peter Dimov and Dave Abrahams for prompting me to write about
this topic and offering the key example, and to John Spicer for helping
me get my head around the rationale for why things are the way they are.
Notes

1. In standardese, a full specialization is called an "explicit
specialization."

2. There is some discussion going on within the committee about
potentially allowing function template partial specialization in the
next version of the C++ standard, whose work is just getting under way.
Copyright © 2009 Herb Sutter

  1. 2011-04-01 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop
  2. 2011-04-01 swd <sderrick-at-optonline.net> RE: [NYLXS - HANGOUT] C++ Workshop
  3. 2011-04-02 swd <sderrick-at-optonline.net> RE: [NYLXS - HANGOUT] Work
  4. 2011-04-05 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] Work
  5. 2011-04-05 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] C++ Workshop
  6. 2011-04-05 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] Re: double deletes C++ Workshop
  7. 2011-04-06 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] [pasa-at-lib.hu: Re: [accu-general] Who uses C?]
  8. 2011-04-06 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop Calendar
  9. 2011-04-06 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop, Linked List Workshop - usenet article.
  10. 2011-04-07 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] Slackware news
  11. 2011-04-07 einker <eminker-at-gmail.com> Re: [NYLXS - HANGOUT] Slackware news
  12. 2011-04-07 einker <eminker-at-gmail.com> Re: [NYLXS - HANGOUT] Slackware news
  13. 2011-04-08 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] [jan.vipin-at-gmail.com: Re: Query about C++ Workshop]
  14. 2011-04-10 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] C++ Workshop Calendar
  15. 2011-04-10 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] Hardware
  16. 2011-04-10 einker <eminker-at-gmail.com> Re: [NYLXS - HANGOUT] Hardware
  17. 2011-04-11 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop
  18. 2011-04-11 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] C++ Workshop
  19. 2011-04-11 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop templated operator()<<]
  20. 2011-04-12 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] NYLUG Workshop / Hacking Society (Smalltalk, C++, Python) Tuesday April 12 6:00PM-8:00PM
  21. 2011-04-12 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] [billy.donahue-at-gmail.com: Re: templated operator()<<]
  22. 2011-04-12 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop Template, claass and function specialization
  23. 2011-04-12 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] C++ Workshop const
  24. 2011-04-15 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] Free Software Round Table TOMORROW, Saturday April 16 10-11 PM (streaming live)
  25. 2011-04-16 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] Free Software Round Table Canceled
  26. 2011-04-17 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop reminder
  27. 2011-04-18 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] Happy Peasach
  28. 2011-04-19 Elfen Magix <elfen_magix-at-yahoo.com> Re: [NYLXS - HANGOUT] Happy Peasach
  29. 2011-04-19 Kevin Mark <kevin.mark-at-verizon.net> Re: [NYLXS - HANGOUT] Happy Peasach
  30. 2011-04-24 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] [nbs-at-sonic.net: [vox] Fwd: Programmng the Kernel...]
  31. 2011-04-24 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] No Workshop tonight
  32. 2011-04-26 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] NYLUG Workshop / Hacking Society (Smalltalk, C++, Python) Tuesday April 26 6:00PM-8:00PM
  33. 2011-04-28 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] NYLUG Presents: 5/18 -at- 6:30PM Cameron L. Fadjo on Construct, Program, Design: Exploring Scratch From the Perspective of Computational Thinking and Cognition
  34. 2011-04-28 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] NYLUG Presents: 5/18 -at- 6:30PM Cameron L. Fadjo
  35. 2011-04-28 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] NYLUG Presents: 5/18 -at- 6:30PM Cameron L. Fadjo
  36. 2011-04-29 Ron Guerin <ron-at-vnetworx.net> Subject: [NYLXS - HANGOUT] Free Software Round Table TOMORROW, Saturday April 30 10-11 PM (streaming live)
  37. 2011-04-29 Ron Guerin <ron-at-vnetworx.net> Re: [NYLXS - HANGOUT] NYLUG Presents: 5/18 -at- 6:30PM Cameron L. Fadjo
  38. 2011-04-29 einker <eminker-at-gmail.com> Subject: [NYLXS - HANGOUT] Bellingham's LinuxFest Northwest
  39. 2011-04-29 Ruben Safir <mrbrklyn-at-panix.com> Re: [NYLXS - HANGOUT] Bellingham's LinuxFest Northwest
  40. 2011-04-29 Ruben Safir <mrbrklyn-at-panix.com> Subject: [NYLXS - HANGOUT] C++ Workshop - New Webservices with OKWS - Sunday evening

NYLXS are Do'ers and the first step of Doing is Joining! Join NYLXS and make a difference in your community today!