Namespace issue with specialized swap

481 views
Skip to first unread message

nik...@my-deja.com

unread,
Mar 12, 2000, 3:00:00 AM3/12/00
to
A specialized swap function can often be more efficient than
the general purpose version. But if I implement a swap function
for a class which is in a namespace, how can I make sure my
function gets called instead of std::swap?

Following is a program that demonstrates the problem. Namespace
"A" contains a stripped-down smart pointer class P, which has
a specialized swap function. To help Illustrate, I made P
non-assignable so that calling std::swap produces an error.

namespace A {

template<class T>
class P {
public:
P(T* in) { p = in; }
~P() { delete p; }

void swap(P& arg) {
T* temp = p;
p = arg.p;
arg.p = temp; }

friend void swap(P& p1, P& p2) {
p1.swap(p1); }

private:
T* p;
P& operator=(const P& rhs);
P(const P& rhs);
};
};

template<class T>
void MyFunc(T& lhs, T& rhs)
{
std::swap(lhs, rhs);
}

namespace std {

template<class T>
void standard_function(T& lhs, T& rhs)
{
swap(lhs, rhs);
}
}

int main()
{
using namespace std;
using namespace A;

P<int> p1 = new int(1);
P<int> p2 = new int(2);

swap(p1, p2);
MyFunc(p1, p2);
standard_function(p1, p2);

return 0;
}


Let's look at the three calls to swap in this program. First,
the call to swap in the main function resolves to A::swap, which
is what I want. That's because main "uses" both namespaces, so
A::swap and std::swap are equally visible.

Second, the MyFunc function contains no using statements so it
explicitly specifies the std namespace. Not surprisingly, this
results in a call to std::swap, which for class P results in a
compile-time error.

Finally, I included standard_function to illustrate what might
happen if I used my class with a hypothetical standard library
function. Since this function is itself in the std namespace,
its call to swap results in a call to std::swap.

None of this is terribly surprising, but it leads me to wonder:
if I take the trouble to write a specialized swap function, how
can I make sure it gets called? The only solution I can think of
is to put my swap function in the std namespace, but this seems
like a no-no. Any suggestions?


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]


Darin Adler

unread,
Mar 13, 2000, 3:00:00 AM3/13/00
to
In article <8abr6r$478$1...@nnrp1.deja.com>, nik...@my-deja.com wrote:

> None of this is terribly surprising, but it leads me to wonder:
> if I take the trouble to write a specialized swap function, how
> can I make sure it gets called? The only solution I can think of
> is to put my swap function in the std namespace, but this seems
> like a no-no. Any suggestions?

Your swap should go in the std namespace. A *specialization* of
std::swap is allowed for non-template classes because of the following
clause in the standard (part of 17.4.3.1/1):

"A program may add template specializations for any standard library
template to namespace std. Such a specialization (complete or partial)
of a standard library template results in undefined behavior unless the
declaration depends on a user-defined name of external linkage and
unless the specialization meets the standard library requirements for
the original template."

Unfortunately, as I understand it, for a template class, putting your
swap in the standard namespace requires an overload of the std::swap
function template rather than a specialization. This overload has pretty
much the same effect as a specialization, but it's theoretically illegal
because the clause above only talks about specializations.

My approach has been to put the overload in namespace std and hope that
the standard gets revised to allow this some day. For example, I did
this in the Boost <http://www.boost.org> header smart_ptr.hpp for the
class templates shared_ptr and shared_array.

Someone should write a defect report about this issue eventually. I
haven't been able to boil down the thing to my satisfaction which is why
I haven't written one yet.

-- Darin

Siemel B. Naran

unread,
Mar 13, 2000, 3:00:00 AM3/13/00
to
On 12 Mar 2000 06:59:29 -0500, nik...@my-deja.com <nik...@my-deja.com> wrote:

>A specialized swap function can often be more efficient than
>the general purpose version. But if I implement a swap function
>for a class which is in a namespace, how can I make sure my
>function gets called instead of std::swap?

namespace std
{
void swap(P& lhs, P& rhs) { lhs.swap(rhs); }
}

--
--------------
siemel b naran
--------------

Howard Hinnant

unread,
Mar 13, 2000, 3:00:00 AM3/13/00
to
In article <8abr6r$478$1...@nnrp1.deja.com>, nik...@my-deja.com wrote:

> Finally, I included standard_function to illustrate what might
> happen if I used my class with a hypothetical standard library
> function. Since this function is itself in the std namespace,
> its call to swap results in a call to std::swap.

This doesn't answer your entire question, but I wanted to point out that
standard_function(p1, p2); will call A::swap because of Koenig lookup.

-Howard

Todd Greer

unread,
Mar 14, 2000, 3:00:00 AM3/14/00
to
nik...@my-deja.com writes:

> None of this is terribly surprising, but it leads me to wonder:
> if I take the trouble to write a specialized swap function, how
> can I make sure it gets called? The only solution I can think of
> is to put my swap function in the std namespace, but this seems
> like a no-no. Any suggestions?

Specializing std templates with user-defined types is explicitly
allowed. Thus, write:

namespace std
{
template<class T>

void swap(P<T>& a, P<T>& b) {...}
}

(I just typed this out without compiling it, so there are probably
mistakes.)

I think this should be the preferred way to write swap, for the
reasons you give.

--
Todd Greer <tgr...@acm.org>

Gabriel Dos Reis

unread,
Mar 15, 2000, 3:00:00 AM3/15/00
to
Todd Greer <tgr...@acm.org> writes:

| nik...@my-deja.com writes:
|
| > None of this is terribly surprising, but it leads me to wonder:
| > if I take the trouble to write a specialized swap function, how
| > can I make sure it gets called? The only solution I can think of
| > is to put my swap function in the std namespace, but this seems
| > like a no-no. Any suggestions?
|
| Specializing std templates with user-defined types is explicitly
| allowed. Thus, write:
|
| namespace std
| {
| template<class T>
| void swap(P<T>& a, P<T>& b) {...}
| }

No, this is wrong.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

alan_gr...@my-deja.com

unread,
Mar 15, 2000, 3:00:00 AM3/15/00
to
In article <uog8hb...@nonsense.dy.natinst.com>,

Todd Greer <tgr...@acm.org> wrote:
>
> Specializing std templates with user-defined types is explicitly
> allowed. Thus, write:
>
> namespace std
> {
> template<class T>
> void swap(P<T>& a, P<T>& b) {...}
> }

The code you give _overloads_ the std::swap<> template function. This
is currently disallowed - although the issue has been discussed in a
number of forums.

A specialisation looks like:

namespace std
{
template<>
void swap(myspace::mytype& a, myspace::mytype& a) { ... }
}

IMHO opinion overloading of standard algorithms based on UDTs (what
you've done) should be allowed. (And is what I do.)

Informally I know what I want the standard to say, but I keep being
distracted from writing a defect report...

... should any std functions be overloadable (e.g. std::abs when I write
a big_integer<> template class).

... if so, what about "impure" functions from the C heritage (e.g.
std::strtok).

... what about interactions with the implicit conversion rules if
"big_integer" has a non-explicit constructor taking a "double".
--
Alan Griffiths (alan.gr...@experian.com, +44 115 934 4517)
Senior Systems Consultant, Experian


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Jonathan Lundquist

unread,
Mar 16, 2000, 3:00:00 AM3/16/00
to
On 15 Mar 2000 23:13:39 -0500, alan_gr...@my-deja.com wrote:

>In article <uog8hb...@nonsense.dy.natinst.com>,
>Todd Greer <tgr...@acm.org> wrote:
>>
>> Specializing std templates with user-defined types is explicitly
>> allowed. Thus, write:
>>
>> namespace std
>> {
>> template<class T>
>> void swap(P<T>& a, P<T>& b) {...}
>> }
>
>The code you give _overloads_ the std::swap<> template function. This
>is currently disallowed - although the issue has been discussed in a
>number of forums.

It looks to me like partial specialisation? Any standard lawyers care
to comment?

>
>A specialisation looks like:
>
>namespace std
>{
> template<>
> void swap(myspace::mytype& a, myspace::mytype& a) { ... }
>}

>...

Gabriel Dos Reis

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
Jonathan Lundquist <j...@sssonline.com> writes:

| On 15 Mar 2000 23:13:39 -0500, alan_gr...@my-deja.com wrote:
|
| >In article <uog8hb...@nonsense.dy.natinst.com>,
| >Todd Greer <tgr...@acm.org> wrote:
| >>
| >> Specializing std templates with user-defined types is explicitly
| >> allowed. Thus, write:
| >>
| >> namespace std
| >> {
| >> template<class T>
| >> void swap(P<T>& a, P<T>& b) {...}
| >> }
| >
| >The code you give _overloads_ the std::swap<> template function. This
| >is currently disallowed - although the issue has been discussed in a
| >number of forums.
|
| It looks to me like partial specialisation? Any standard lawyers care
| to comment?

I'm not a standard lawyer, but I can say for sure that there is not
such as a *partial* specializaton for template function. The above is an
overloading. Given a template function, you can:
o fully specialize it, or
o overload it.

That is all.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Biju Thomas

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
Jonathan Lundquist wrote:
>
> On 15 Mar 2000 23:13:39 -0500, alan_gr...@my-deja.com wrote:
>
> >In article <uog8hb...@nonsense.dy.natinst.com>,
> >Todd Greer <tgr...@acm.org> wrote:
> >>
> >> Specializing std templates with user-defined types is explicitly
> >> allowed. Thus, write:
> >>
> >> namespace std
> >> {
> >> template<class T>
> >> void swap(P<T>& a, P<T>& b) {...}
> >> }
> >
> >The code you give _overloads_ the std::swap<> template function. This
> >is currently disallowed - although the issue has been discussed in a
> >number of forums.
>
> It looks to me like partial specialisation? Any standard lawyers care
> to comment?
>

Not a lawyer, but, the above code is *not* partial specialization, but
overloading. A partial specialization syntax would have been (if it was
legal):

template < class T >
void swap<T> ( P<T>&, P<T>& ) {...}

--
Biju Thomas

Andrei Alexandrescu

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
news:flln3k5...@riz.cmla.ens-cachan.fr...
> No, this is wrong.

As much as I appreciate terseness, this is not too enlighting :o).

C'mon, man - why aren't you more, well, joyful? Reminds me of our discussion
about valarray. You did give us a lot of information, but only after a lot
of persuasion efforts.

Why is that wrong?


Andrei

Darin Adler

unread,
Mar 17, 2000, 3:00:00 AM3/17/00
to
In article <Jg7ROE8lVXxxDp...@4ax.com>, Jonathan Lundquist
<j...@sssonline.com> wrote:

> On 15 Mar 2000 23:13:39 -0500, alan_gr...@my-deja.com wrote:
>
> >In article <uog8hb...@nonsense.dy.natinst.com>,
> >Todd Greer <tgr...@acm.org> wrote:
> >>
> >> Specializing std templates with user-defined types is explicitly
> >> allowed. Thus, write:
> >>
> >> namespace std
> >> {
> >> template<class T>
> >> void swap(P<T>& a, P<T>& b) {...}
> >> }
> >
> >The code you give _overloads_ the std::swap<> template function. This
> >is currently disallowed - although the issue has been discussed in a
> >number of forums.
>
> It looks to me like partial specialisation? Any standard lawyers care
> to comment?

There's no such thing as partial specialization for function templates.
It only exists for class templates. For function templates you get a
similar effect by using one function template to overload another.

Partial specialization of class template is covered in section 14.5.4 of
the standard. The next section, 14.5.5, discusses function template
overloading. There's no section discussing function temlate partial
specialization; it doesn't exist.

-- Darin

Gabriel Dos Reis

unread,
Mar 18, 2000, 3:00:00 AM3/18/00
to
"Andrei Alexandrescu" <andre...@hotmail.com> writes:

[...]

| Why is that wrong?


> Specializing std templates with user-defined types is explicitly
> allowed. Thus, write:

> namespace std
> {
> template<class T>
> void swap(P<T>& a, P<T>& b) {...}
> }

The above is not an explicit template specialization as claimed.
(But you know that. Isn't it?)

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

nik...@my-deja.com

unread,
Mar 18, 2000, 3:00:00 AM3/18/00
to
In article <8ankpq$9da$1...@nnrp1.deja.com>,

alan_gr...@my-deja.com wrote:
> In article <uog8hb...@nonsense.dy.natinst.com>,
> Todd Greer <tgr...@acm.org> wrote:
> >
> > Specializing std templates with user-defined types is explicitly
> > allowed. Thus, write:
> >
> > namespace std
> > {
> > template<class T>
> > void swap(P<T>& a, P<T>& b) {...}
> > }
>
> The code you give _overloads_ the std::swap<> template function. This
> is currently disallowed - although the issue has been discussed in a
> number of forums.
Actually, I don't think it's either a partial specialization
_or_ an overload, but is simply ambiguous. At least, that's
what my compiler thinks, and I think in this case my compiler
is right.
Perhaps the idea that this is an overload derives from the
example (excerpted below) from 14.5.5.2 [temp.func.order]:
template<class T> void h(const T&);
template<class T> void h(A<T>&);
...
h(z); // overload resolution selects h(A<T>&)
Here the comment implies that neither function is more
specialized than the other; therefore the second function
is selected based on the overloading rules. But having
looked at the overloading rules, I think the _only_ reason
this call is not ambiguous is because the first function
takes a const reference!
So if I want to write a specialized version of std::swap
for my own template class, it seems I'm out of luck. If I
don't put my swap function in the std namespace it simply
won't get called in most cases, but if I do put it in the
std namespace it will be ambiguous. No method of resolving
the ambiguity seem to work:
- Partial specialization of templates doesn't help.
- Overloading per 13.3.3 doesn't give a best match.
- Making std::swap a friend might solve the ambiguity,
but can't (I think) be done if my template class
and std::swap are in different namespaces.
This seems like something many people would want to do.
Can it really be impossible?


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 18, 2000, 3:00:00 AM3/18/00
to
nik...@my-deja.com writes:

| In article <8ankpq$9da$1...@nnrp1.deja.com>,
| alan_gr...@my-deja.com wrote:
| > In article <uog8hb...@nonsense.dy.natinst.com>,
| > Todd Greer <tgr...@acm.org> wrote:
| > >
| > > Specializing std templates with user-defined types is explicitly
| > > allowed. Thus, write:
| > >
| > > namespace std
| > > {
| > > template<class T>
| > > void swap(P<T>& a, P<T>& b) {...}
| > > }
| >
| > The code you give _overloads_ the std::swap<> template function. This
| > is currently disallowed - although the issue has been discussed in a
| > number of forums.
| Actually, I don't think it's either a partial specialization
| _or_ an overload, but is simply ambiguous.

???

13/1:
When two or more different declarations are specified for a single
name in the same scope, that name is said to be overloaded. [...]

| ... At least, that's


| what my compiler thinks, and I think in this case my compiler
| is right.
| Perhaps the idea that this is an overload derives from the
| example (excerpted below) from 14.5.5.2 [temp.func.order]:
| template<class T> void h(const T&);
| template<class T> void h(A<T>&);

No, it comes from the standard definition.

| ...
| h(z); // overload resolution selects h(A<T>&)
| Here the comment implies that neither function is more
| specialized than the other; therefore the second function
| is selected based on the overloading rules. But having
| looked at the overloading rules, I think the _only_ reason
| this call is not ambiguous is because the first function
| takes a const reference!

Well, partial ordering rules and overloading resolution rules are
different concepts from the concept of "overloading".

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Andrei Alexandrescu

unread,
Mar 18, 2000, 3:00:00 AM3/18/00
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
news:flhfe5f...@poivre.cmla.ens-cachan.fr...
[snip]

> > namespace std
> > {
> > template<class T>
> > void swap(P<T>& a, P<T>& b) {...}
> > }
>
> The above is not an explicit template specialization as claimed.
> (But you know that. Isn't it?)

(I didn't.)
Ah, you mean only total specializations of std functions are allowed? Like:

namespace std
{
template<>
void swap(P<int>& a, P<int>& b) {...}
}

In this case, we're kinda stuck. If we develop a matrix class template,
we're not able to make swap matrices of any type efficiently.


Andrei

Andrei

Gabriel Dos Reis

unread,
Mar 19, 2000, 3:00:00 AM3/19/00
to
"Andrei Alexandrescu" <andre...@hotmail.com> writes:

| Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
| news:flhfe5f...@poivre.cmla.ens-cachan.fr...
| [snip]
| > > namespace std
| > > {
| > > template<class T>
| > > void swap(P<T>& a, P<T>& b) {...}
| > > }
| >
| > The above is not an explicit template specialization as claimed.
| > (But you know that. Isn't it?)
|
| (I didn't.)

I'm surprised ;-)

| Ah, you mean only total specializations of std functions are allowed? Like:
|
| namespace std
| {
| template<>
| void swap(P<int>& a, P<int>& b) {...}
| }

Yes. The standard says:

17.4.3.1/1
It is undefined for a C++ program to add declarations or definitions
to namespace std or namespaces with namespace std unless otherwise
specified. A program may add template specializations for any


standard library template to namespace std. Such a specialization

(complete or partial) of a standard library results in undefined
behaviour unless the declaration depends on a user-defined name of
external linkage and unless the template specialization meets the


standard library requirements for the original template.

| In this case, we're kinda stuck. If we develop a matrix class template,
| we're not able to make swap matrices of any type efficiently.

Please, could you elaborate on this a little bit?

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Andrei Alexandrescu

unread,
Mar 19, 2000, 3:00:00 AM3/19/00
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
news:flityj5...@poivre.cmla.ens-cachan.fr...

> | In this case, we're kinda stuck. If we develop a matrix class template,
> | we're not able to make swap matrices of any type efficiently.
>
> Please, could you elaborate on this a little bit?

I meant: I make a Matrix class template. Then I want to implement an


efficient swap for it. I then write:

namespace std
{
template <class T> inline void swap(Matrix<T>& lhs, Matrix<T>& rhs)
{
...
}
}

What you say implies that I must write:

namespace std
{
template <> inline void swap(Matrix<int>& lhs, Matrix<int>& rhs)
{
...
}
template <> inline void swap(Matrix<double>& lhs, Matrix<double>& rhs)
{
...
}
...
}

Is that correct? After all, how does one call a partial ordering of
functions? Does it count as overloading?


Andrei

Ross Smith

unread,
Mar 19, 2000, 3:00:00 AM3/19/00
to
"Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message
news:flityj5...@poivre.cmla.ens-cachan.fr...
> "Andrei Alexandrescu" <andre...@hotmail.com> writes:
>
> | Ah, you mean only total specializations of std functions are
allowed? Like:
> |
> | namespace std
> | {
> | template<>
> | void swap(P<int>& a, P<int>& b) {...}
> | }
>
> Yes. The standard says:
>
> 17.4.3.1/1
> It is undefined for a C++ program to add declarations or definitions
> to namespace std or namespaces with namespace std unless otherwise
> specified. A program may add template specializations for any
> standard library template to namespace std. Such a specialization
> (complete or partial) of a standard library results in undefined
> behaviour unless the declaration depends on a user-defined name of
> external linkage and unless the template specialization meets the
> standard library requirements for the original template.

I don't see how this supports your claim. It seems to me to say that
partial specialisation *is* allowed if it depends on a user-defined name
(as in Andrei's earlier example).

--
Ross Smith <ros...@ihug.co.nz> The Internet Group, Auckland, New Zealand
========================================================================
"So that's 2 T-1s and a newsfeed ... would you like clues with that?"
-- Peter Da Silva

Gabriel Dos Reis

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
"Andrei Alexandrescu" <andre...@hotmail.com> writes:

| Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote in message
| news:flityj5...@poivre.cmla.ens-cachan.fr...

| > | In this case, we're kinda stuck. If we develop a matrix class template,
| > | we're not able to make swap matrices of any type efficiently.
| >
| > Please, could you elaborate on this a little bit?
|
| I meant: I make a Matrix class template. Then I want to implement an
| efficient swap for it. I then write:
|
| namespace std
| {
| template <class T> inline void swap(Matrix<T>& lhs, Matrix<T>& rhs)
| {
| ...
| }
| }
|
| What you say implies that I must write:
|
| namespace std
| {
| template <> inline void swap(Matrix<int>& lhs, Matrix<int>& rhs)
| {
| ...
| }
| template <> inline void swap(Matrix<double>& lhs, Matrix<double>& rhs)
| {
| ...
| }
| ...
| }
|
| Is that correct?

No. What the standard says is that if you *insist* to put
'swap(Matrix<>&, Matrix<>&)' in namespace std, then you don't have the
choice: Matrix<> must be full specialization, it can't depend on a
template parameter.

Why can't you put 'swap(Matrix<>&, Matrix<>&)' in Matrix's namespace
definition?

| ... After all, how does one call a partial ordering of


| functions? Does it count as overloading?

Partial ordering of template function is a _rule_ used to select a
template function declaration associated with a function template
specialization in case the function template is overloaded.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
"Ross Smith" <ros...@ihug.co.nz> writes:

| "Gabriel Dos Reis" <dos...@cmla.ens-cachan.fr> wrote in message
| news:flityj5...@poivre.cmla.ens-cachan.fr...

| > "Andrei Alexandrescu" <andre...@hotmail.com> writes:
| >
| > | Ah, you mean only total specializations of std functions are
| allowed? Like:
| > |
| > | namespace std
| > | {
| > | template<>
| > | void swap(P<int>& a, P<int>& b) {...}
| > | }
| >
| > Yes. The standard says:
| >
| > 17.4.3.1/1
| > It is undefined for a C++ program to add declarations or definitions
| > to namespace std or namespaces with namespace std unless otherwise
| > specified. A program may add template specializations for any
| > standard library template to namespace std. Such a specialization
| > (complete or partial) of a standard library results in undefined
| > behaviour unless the declaration depends on a user-defined name of
| > external linkage and unless the template specialization meets the
| > standard library requirements for the original template.
|
| I don't see how this supports your claim. It seems to me to say that
| partial specialisation *is* allowed if it depends on a user-defined name
| (as in Andrei's earlier example).

But as I said in another message

template<typename T>
void swap(P<T>&, P<T>&) { /* ... */ }

is *not* a partial specialization. It is an overloading. Thus
it can be put put in namespace std, as per the rule quoted above.

There is nothing named *template function partial specialization*.
The only thing you have with template function is
o explicit (i.e. full) specialization
o overloading.

That is all.

alan_gr...@my-deja.com

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
In article <8b3ctg$ni3$1...@news.ihug.co.nz>,

"Ross Smith" <ros...@ihug.co.nz> wrote:
> I don't see how this supports your claim. It seems to me to say that
> partial specialisation *is* allowed if it depends on a user-defined
name
> (as in Andrei's earlier example).

Before partial specialisation is allowed it must exist:

In article <darin-CBCBF4....@fullnews.metawire.com>,


Darin Adler <da...@bentspoon.com> wrote:
> There's no such thing as partial specialization for function
templates.
> It only exists for class templates. For function templates you get a
> similar effect by using one function template to overload another.
>
> Partial specialization of class template is covered in section 14.5.4
of
> the standard. The next section, 14.5.5, discusses function template
> overloading. There's no section discussing function temlate partial
> specialization; it doesn't exist.

(I.e. Andrei's earlier example overloads the swap template.)

There are many reasons to want to provide "partial specialisations" of
the standard algorithms (such as Andrei's Matrix). But it is not
allowed by the language - the obvious alternative of overloading in
namespace std is better (only "undefined behavior") but not ideal.

An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
namespace that contains Matrix - but that has problems too. (Think of
writing code that uses Matrix in a class with a swap() member function.
Too easy? Try a template class that could be passed Matrix as a
parameter.)

This last can be made to work if the writer of the client code is
sufficiently aware of the issues - but I don't think that requirement is
acceptable. Look at the current thread - the participants are all
"above average" in their knowledge and interest in standard C++. The
name lookup problem and the route around it are similarly obscure (i.e.
you only know about it after being bitten).

PS

I'm not the only one that knowingly relies on "undefined behavior" in
this area - check out the boost smart pointers (http://www.boost.org/).
AFAIK there is no ideal solution in the language as currently defined.
When I can work out what the standard should say I'll submit a defect
report. (But this isn't easy either.)


--
Alan Griffiths (alan.gr...@experian.com, +44 115 934 4517)
Senior Systems Consultant, Experian

Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> writes:

[...]

| But as I said in another message
|
| template<typename T>
| void swap(P<T>&, P<T>&) { /* ... */ }
|
| is *not* a partial specialization. It is an overloading. Thus
| it can be put put in namespace std, as per the rule quoted above.

^^^^^^^^^^
I meant: "it cannot be put"

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
alan_gr...@my-deja.com writes:

[...]

| An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
| namespace that contains Matrix - but that has problems too. (Think of
| writing code that uses Matrix in a class with a swap() member function.
| Too easy? Try a template class that could be passed Matrix as a
| parameter.)

I think that in such cases, on can use non-member function swap() in
an unqualified manner and let Koenig lookup to do the right thing.

nik...@my-deja.com

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
In article <flwvn08...@poivre.cmla.ens-cachan.fr>,

Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
> nik...@my-deja.com writes:
>
> | In article <8ankpq$9da$1...@nnrp1.deja.com>,
> | alan_gr...@my-deja.com wrote:
> | > In article <uog8hb...@nonsense.dy.natinst.com>,
> | > Todd Greer <tgr...@acm.org> wrote:
> | > >
> | > > Specializing std templates with user-defined types is explicitly
> | > > allowed. Thus, write:
> | > >
> | > > namespace std
> | > > {
> | > > template<class T>
> | > > void swap(P<T>& a, P<T>& b) {...}
> | > > }
> | >
> | > The code you give _overloads_ the std::swap<> template function.
This
> | > is currently disallowed - although the issue has been discussed
in a
> | > number of forums.
> | Actually, I don't think it's either a partial specialization
> | _or_ an overload, but is simply ambiguous.
>
> ???
>
> 13/1:
> When two or more different declarations are specified for a single
> name in the same scope, that name is said to be overloaded. [...]

Allow me to restate my point without abusing the term overload.
Given the two function declarations,

namespace std {

// The standard version.
template<class T>
void swap(T& arg1, T& arg2);

// The version for my template class.
template<class T>
void swap(MyType<T>& arg1, MyType<T>& arg2);
}

the second function can *never* be called. Attempting to do so
results in abiguity, e.g.,

MyType<int> a;
MyType<int> b;
std::swap(a, b); // ambiguous

Because of this, I mistakenly asserted that the two functions
are not overloaded. It would be more accurate to say that
overloading doesn't solve my problem. That problem once
again is:

How can I write a swap function for my template class
in such a way that my function will always be called
instead of the general-purpose std::swap function.

So far, I am no nearer a solution. In particular, it appears
that the solution used by the boost.org smart pointers is no
solution at all -- even if one is willing to flout the rule
that says you can't overload standard functions in the std
namespace.


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Thomas Maeder

unread,
Mar 20, 2000, 3:00:00 AM3/20/00
to
Gabriel Dos Reis schrieb:

>
> Why can't you put 'swap(Matrix<>&, Matrix<>&)' in Matrix's namespace
> definition?

Because the option of specializing Standard library classes and functions
was ruled in to provide compile-time specialization.

Say I have this program:

int main()
{
std::vector<int> v1,v2;
// initialization of v1 and v2

std::swap(v1,v2); // ok
}

If I then decide to substitute a container class template of my own for
std::vector, I have to change the call to swap, too. Not nice.

Hyman Rosen

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
nik...@my-deja.com writes:
> Given the two function declarations,
> namespace std {
> template<class T>
> void swap(T& arg1, T& arg2);
> template<class T>
> void swap(MyType<T>& arg1, MyType<T>& arg2);
> }
> the second function can *never* be called. Attempting to do so
> results in abiguity, e.g.,
>
> MyType<int> a;
> MyType<int> b;
> std::swap(a, b); // ambiguous

This is false. In 13.3.3 we learn that for a pair of overloaded
function templates, the more specialized one is preferred, and
14.5.5.2 tells us that the second function is more specialized
than the first.

Darin Adler

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
In article <8b5o9t$la4$1...@nnrp1.deja.com>, nik...@my-deja.com wrote:

> Allow me to restate my point without abusing the term overload.

> Given the two function declarations,
>
> namespace std {
>

> // The standard version.


> template<class T>
> void swap(T& arg1, T& arg2);
>

> // The version for my template class.

> template<class T>
> void swap(MyType<T>& arg1, MyType<T>& arg2);
> }
>
> the second function can *never* be called. Attempting to do so
> results in abiguity, e.g.,
>
> MyType<int> a;
> MyType<int> b;
> std::swap(a, b); // ambiguous

This is wrong. The version for your template class (an overload of the
standard version) will be called because it's a better match. It is not
ambiguous according to the standard nor according to my compiler.

The relevant part of the standard is 13.3.3/1 says that a template
function that is "more specialized" will win. 14.5.5.2 defines what
"more specialized" means. In this case, the version of swap for your
template class wins.

The only thing wrong with the code above is that the standard explicitly
forbids adding things to namespace std, with an exception for partial
specializations depending on user-defined types. Since the above is an
overload, not a partial specialization it does not qualify for the
exception and the standard forbids it.

-- Darin

Todd Greer

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
alan_gr...@my-deja.com writes:

> > template<class T>
> > void swap(P<T>& a, P<T>& b) {...}

> The code you give _overloads_ the std::swap<> template function. This
> is currently disallowed - although the issue has been discussed in a
> number of forums.

Aack! I had thought you could write partial specializations of
template functions, and that I had written one. Thank you for the
correction.

I think allowing partial specialization of functions might be better
than allowing overloading std functions, because it would then be a
small step towards partial member function specialization, and then
Andrei would finally be happy. (I'm not making fun of him--he has
legit reasons.)

If it weren't for the frequency with which someone points out how
wrong I am in my posts, I would know less C++.

--
Todd Greer <tgr...@acm.org>

Jonathan Lundquist

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
On 20 Mar 2000 05:50:16 -0500, Gabriel Dos Reis
<dos...@cmla.ens-cachan.fr> wrote:

>
>But as I said in another message
>
> template<typename T>
> void swap(P<T>&, P<T>&) { /* ... */ }
>
>is *not* a partial specialization. It is an overloading. Thus
>it can be put put in namespace std, as per the rule quoted above.

Whatever we call that thing above, can anyone give a good reason why
it isn't allowed in std (besides the standard says so). Is there any
scenario where ambiguities arise provided 'P' is a user defined
template? Is this an oversight in the standard?

>
>There is nothing named *template function partial specialization*.
>The only thing you have with template function is
> o explicit (i.e. full) specialization
> o overloading.
>
>That is all.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Darin Adler

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
alan_gr...@my-deja.com writes:

> | An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
> | namespace that contains Matrix - but that has problems too. (Think of
> | writing code that uses Matrix in a class with a swap() member function.
> | Too easy? Try a template class that could be passed Matrix as a
> | parameter.)

In article <fl7lexz...@poivre.cmla.ens-cachan.fr>, Gabriel Dos Reis
<dos...@cmla.ens-cachan.fr> wrote:

> I think that in such cases, on can use non-member function swap() in
> an unqualified manner and let Koenig lookup to do the right thing.

It's true that non-member function in the same namespace as Matrix is
allowed by the standard, and overloading the swap function in the
standard namespace is not allowed by the standard.

Unfortunately, relying on Koenig lookup in this way means that template
programmers have to use "using" rather than "std::" to get at standard
functions like swap. For example:

template <typename T, typename U>
swap_first_elements (std::pair<T,U>& p, std::pair<T,U>& q) {
std::swap (p.first, q.first);
}

If T has an improved swap in its own namespace, the above function
template will not take advantage of it.

template <typename T, typename U>
swap_first_elements (std::pair<T,U>& p, std::pair<T,U>& q) {
using std::swap;
swap (p.first, q.first);
}

Only this second form will use Koenig lookup.

-- Darin

Andrei Alexandrescu

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
<alan_gr...@my-deja.com> wrote in message
news:8b4ua3$2kp$1...@nnrp1.deja.com...

> There are many reasons to want to provide "partial specialisations" of
> the standard algorithms (such as Andrei's Matrix). But it is not
> allowed by the language - the obvious alternative of overloading in
> namespace std is better (only "undefined behavior") but not ideal.

If this is true, I think someone should file a Defect Report.

I certainly expect that when I call std::swap(a, b) to swap the two
elements. Some STL algorithms expect this, too. If a class does not support
efficient swapping with the stock algorithm (T temp(lhs); lhs = rhs; rhs =
temp), then it is that class' responsibility to fiddle with std::swap.

Forbidding partial ordering or overloading or whatever you call it for
std::swap makes it practically impossible for template class writers to
provide appropriate std::swap semantics.

I am also certain the Standard *does* intend to give programmers and library
writers this opportunity.

Therefore, I think a defect report should be submitted.

> An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
> namespace that contains Matrix - but that has problems too.

I don't think that's even an option. Client code may call std::swap
explicitly, and I don't think that's an error.

> Look at the current thread - the participants are all
> "above average" in their knowledge and interest in standard C++.

A good means to attract people to this thread :o).


Andrei

Gabriel Dos Reis

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
Thomas Maeder <mae...@glue.ch> writes:

| Gabriel Dos Reis schrieb:
| >
| > Why can't you put 'swap(Matrix<>&, Matrix<>&)' in Matrix's namespace
| > definition?
|
| Because the option of specializing Standard library classes and functions
| was ruled in to provide compile-time specialization.
|
| Say I have this program:
|
| int main()
| {
| std::vector<int> v1,v2;
| // initialization of v1 and v2
|
| std::swap(v1,v2); // ok
| }
|
| If I then decide to substitute a container class template of my own for
| std::vector, I have to change the call to swap, too.

Not if you just said:

swap(v1, v2);

Koenig lookup will take care of you.

Writing "std::swap" is strong a requirement -- as any form of
qualified-id use. If you want flexible programms, then you have to be
flexible in your requirements.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

alan_gr...@my-deja.com

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
In article <8b5o9t$la4$1...@nnrp1.deja.com>,
nik...@my-deja.com wrote:
>
> namespace std {
>
> // The standard version.
> template<class T>
> void swap(T& arg1, T& arg2);
>
> // The version for my template class.
> template<class T>
> void swap(MyType<T>& arg1, MyType<T>& arg2);
> }

If, for example, you substitute std::vector for "MyType" this is exactly
what the standard library does.

> the second function can *never* be called. Attempting to do so
> results in abiguity, e.g.,

No it doesn't - see 14.5.5.2. I suspect you have encountered a compiler
bug.

--
Alan Griffiths (alan.gr...@experian.com, +44 115 934 4517)
Senior Systems Consultant, Experian

Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

alan_gr...@my-deja.com

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
> alan_gr...@my-deja.com writes:
>
> [...]

>
> | An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
> | namespace that contains Matrix - but that has problems too. (Think
of
> | writing code that uses Matrix in a class with a swap() member
function.
> | Too easy? Try a template class that could be passed Matrix as a
> | parameter.)
>
> I think that in such cases, on can use non-member function swap() in
> an unqualified manner and let Koenig lookup to do the right thing.

No you can't - note "in a class with a swap() member function". (You'll
probably get a compile error).

The obvious (but wrong) approach is to add "using std::swap".

The right approach in the generic case is to use a _non-member_ function
in your library that looks like:

template<typename type>
inline name_dependent_swap(type& lhs, type& rhs)
{
using std::swap;
swap(lhs, rhs);
}

But remember - the "you" here isn't the author of Matrix - it is every
author of a template class that _might_ be used with Matrix.

(And, of course, the problem applies to find<> and other algorithms, not
just swap.)

Requiring every author to successfully jump this hoop is unrealistic.

Gabriel Dos Reis

unread,
Mar 21, 2000, 3:00:00 AM3/21/00
to
nik...@my-deja.com writes:

[...]

| Allow me to restate my point without abusing the term overload.
| Given the two function declarations,
|

| namespace std {
|
| // The standard version.
| template<class T>
| void swap(T& arg1, T& arg2);
|
| // The version for my template class.
| template<class T>
| void swap(MyType<T>& arg1, MyType<T>& arg2);

As said in another message, this may result in undefined behaviour.
But let's assume it won't.

| }
|
| the second function can *never* be called.

I, still, can't see any reason that supports this claim.

| ... Attempting to do so
| results in abiguity, e.g.,
|

| MyType<int> a;
| MyType<int> b;
| std::swap(a, b); // ambiguous

Why?

Template argument deduction yields:

o swap<MyType<int> >(MyType<int>&, MyType<int>&)
o swap<int>(MyType<int>&, MyType<int>&)


Now, partial ordering (14.5.5.2) says that the function template

template<typename T> swap(MyType<T>&, MyType<T>&)

is more specialized than

template<typename T> swap(T&, T&)

so swap<int>(MyType<T>&, MyType<T>&) should be selected.

Am I overlooking something?

| Because of this, I mistakenly asserted that the two functions
| are not overloaded. It would be more accurate to say that
| overloading doesn't solve my problem. That problem once
| again is:
|
| How can I write a swap function for my template class
| in such a way that my function will always be called
| instead of the general-purpose std::swap function.

Just put it in the namespace of your class template definition.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
Darin Adler <da...@bentspoon.com> writes:

[...]

| Only this second form will use Koenig lookup.

Yes, you made a good summary of the situation.

Personnally, I think that calling a function through a qualified-id in
an unknown context is strong a requirement. In heavy template-based
code I thing that using-declarations and Koenig lookup do provide an
extremely flexible device.

Gabriel Dos Reis

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
"Andrei Alexandrescu" <andre...@hotmail.com> writes:

| <alan_gr...@my-deja.com> wrote in message
| news:8b4ua3$2kp$1...@nnrp1.deja.com...
| > There are many reasons to want to provide "partial specialisations" of
| > the standard algorithms (such as Andrei's Matrix). But it is not
| > allowed by the language - the obvious alternative of overloading in
| > namespace std is better (only "undefined behavior") but not ideal.
|
| If this is true, I think someone should file a Defect Report.
|
| I certainly expect that when I call std::swap(a, b) to swap the two
| elements. Some STL algorithms expect this, too. If a class does not support
| efficient swapping with the stock algorithm (T temp(lhs); lhs = rhs; rhs =
| temp), then it is that class' responsibility to fiddle with std::swap.

Not necessarily std::swap. It suffices it provides swap(). The
language has the necessary mechanics to select the right function.
Assuming of course that that mechanics are used appropriately.

| Forbidding partial ordering or overloading or whatever you call it for
| std::swap makes it practically impossible for template class writers to
| provide appropriate std::swap semantics.

No, they can. Koenig lookup is there to solve such problems.

Gabriel Dos Reis

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
alan_gr...@my-deja.com writes:

| In article <fl7lexz...@poivre.cmla.ens-cachan.fr>,
| Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
| > alan_gr...@my-deja.com writes:
| >
| > [...]
| >
| > | An alternative is to provide swap<>(Matrix<T>&, Matrix<T>&) in the
| > | namespace that contains Matrix - but that has problems too. (Think
| of
| > | writing code that uses Matrix in a class with a swap() member
| function.
| > | Too easy? Try a template class that could be passed Matrix as a
| > | parameter.)
| >
| > I think that in such cases, on can use non-member function swap() in
| > an unqualified manner and let Koenig lookup to do the right thing.
|
| No you can't - note "in a class with a swap() member function". (You'll
| probably get a compile error).

Well, perhaps I was unclear but I suggesting to define a non-member
function as you describe in the rest of your message.

| The obvious (but wrong) approach is to add "using std::swap".
|
| The right approach in the generic case is to use a _non-member_ function
| in your library that looks like:
|
| template<typename type>
| inline name_dependent_swap(type& lhs, type& rhs)
| {
| using std::swap;
| swap(lhs, rhs);
| }

This is exactly what I suggested on the boost list reflector when we
were discussing abs() for a template rational class.

| But remember - the "you" here isn't the author of Matrix - it is every
| author of a template class that _might_ be used with Matrix.
|
| (And, of course, the problem applies to find<> and other algorithms, not
| just swap.)
|
| Requiring every author to successfully jump this hoop is unrealistic.

As unrealistic as to require every author of template library to learn
about template and the two-phase name lookup mechanics (or at least to
be competent)?

nik...@my-deja.com

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
In article <fl66ugv...@pizza.cmla.ens-cachan.fr>,

Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
> nik...@my-deja.com writes:
>
> [...]
>
> | Allow me to restate my point without abusing the term overload.
> | Given the two function declarations,
> |
> | namespace std {
> |
> | // The standard version.
> | template<class T>
> | void swap(T& arg1, T& arg2);
> |
> | // The version for my template class.
> | template<class T>
> | void swap(MyType<T>& arg1, MyType<T>& arg2);
>
> As said in another message, this may result in undefined behaviour.
> But let's assume it won't.

Agreed on both counts.

> | }
> |
> | the second function can *never* be called.
>
> I, still, can't see any reason that supports this claim.
>
> | ... Attempting to do so
> | results in abiguity, e.g.,
> |
> | MyType<int> a;
> | MyType<int> b;
> | std::swap(a, b); // ambiguous
>
> Why?
>
> Template argument deduction yields:
>
> o swap<MyType<int> >(MyType<int>&, MyType<int>&)
> o swap<int>(MyType<int>&, MyType<int>&)

Yes.

>
> Now, partial ordering (14.5.5.2) says that the function template
>
> template<typename T> swap(MyType<T>&, MyType<T>&)
>
> is more specialized than
>
> template<typename T> swap(T&, T&)
>
> so swap<int>(MyType<T>&, MyType<T>&) should be selected.
>
> Am I overlooking something?

This is the part I'm questioning, but I don't really understand
the partial ordering rules so I may be wrong. Let me try to
break it down into steps.

Section 14.5.5.2 paragraphs 2-3 say the two function templates
are transformed as follows:

; Replace T with MyType<int> in first template.
swap(MyType<int>&, MyType<int>&);

; Replace T with int in second template.
swap(MyType<int>&, MyType<int>&);

Next paragraph 4 has us perform argument deduction for each
template against the parameter list of the opposite function.
Because both succeed without requiring any type conversions
we conclude that each template is at least as specialized as
the other; therefore (paragraph 5) neither is more specialized
than the other.

I realize examples are non-normative, but the example in
this section seems to reinforce the above analysis:

...


template<class T> void h(const T&);
template<class T> void h(A<T>&);

...
h(z); // overload resolution selects h(A<T>&)

...

The comment implies that neither function template is
"more specialized" than the other; the call would be
amgiguous except that overload resolution selects the
function that takes a non-const reference.

> | Because of this, I mistakenly asserted that the two functions
> | are not overloaded. It would be more accurate to say that
> | overloading doesn't solve my problem. That problem once
> | again is:
> |
> | How can I write a swap function for my template class
> | in such a way that my function will always be called
> | instead of the general-purpose std::swap function.
>
> Just put it in the namespace of your class template definition.

But will Koenig lookup find my version of swap if the caller
uses an explicit namespace qualifer as in the above example?


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

alan_gr...@my-deja.com

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
In article <fln1ntu...@pizza.cmla.ens-cachan.fr>,

Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
> Thomas Maeder <mae...@glue.ch> writes:
>
> | Gabriel Dos Reis schrieb:
> | >
> | > Why can't you put 'swap(Matrix<>&, Matrix<>&)' in Matrix's
namespace
> | > definition?
> |
> | Because the option of specializing Standard library classes and
functions
> | was ruled in to provide compile-time specialization.
> |
> | Say I have this program:
> |
> | int main()
> | {
> | std::vector<int> v1,v2;
> | // initialization of v1 and v2
> |
> | std::swap(v1,v2); // ok
> | }

A better example (because it prevents Gabriel's solution) is:

struct example
{
std::vector<int> v;

void swap(example& that) // Swap this and that
{
std::swap(v, that.v); // OK
}
};

> |
> | If I then decide to substitute a container class template of my own
for
> | std::vector, I have to change the call to swap, too.

Exactly.

> Not if you just said:
>
> swap(v1, v2);

In the revised example name lookup only finds example::swap() - which
causes a compile error.

> Koenig lookup will take care of you.

Not in the revised example.

The right approach is:

template<typename type>
inline name_dependent_swap(type& lhs, type& rhs)
{
using std::swap;
swap(lhs, rhs);
}


struct example
{
std::vector<int> v;

void swap(example& that) // Swap this and that
{
name_dependent_swap(v, that.v);
}
};

--
Alan Griffiths (alan.gr...@experian.com, +44 115 934 4517)
Senior Systems Consultant, Experian

Dave Abrahams

unread,
Mar 22, 2000, 3:00:00 AM3/22/00
to
in article fl66ugv...@pizza.cmla.ens-cachan.fr, Gabriel Dos Reis at
dos...@cmla.ens-cachan.fr wrote on 3/21/00 12:24 PM:

> | How can I write a swap function for my template class
> | in such a way that my function will always be called
> | instead of the general-purpose std::swap function.
>
> Just put it in the namespace of your class template definition.

Really that depends on how algorithm implementors decide to respond to the
unfortunate dilemma given to us by whoever designed this part of the
language. There are several possible choices:

1. Just use unqualified swap() and rely on Koenig lookup to find the right
version. This effectively reserves the name "swap" in ALL namespaces. If
someone should write a 2-argument swap function with different semantics
(admittedly unlikely, but think of copy or some of the other standard
algorithms), the standard algorithms would be broken.

2. Use qualified std::swap() and be sure that you're getting the right
semantics. Actually, the only place the standard mentions using swap for an
algorithm is in the reverse() algorithm, and even there it seems rather
unclear whether the intention is to use Koenig lookup or not.

3. Don't use swap at all. Probably OK for everything but reverse().

-Dave

Carl Barron

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:

> Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> writes:
>
> [...]
>

> | But as I said in another message
> |
> | template<typename T>
> | void swap(P<T>&, P<T>&) { /* ... */ }
> |
> | is *not* a partial specialization. It is an overloading. Thus
> | it can be put put in namespace std, as per the rule quoted above.

> ^^^^^^^^^^
> I meant: "it cannot be put"

Well what does your <vector> file do to define swap for vectors??
I'd bet it says something like:

template <class T,class A>
void swap(vector<T,A> &,vector<T,A> & y) {x.swap(y);}

mine does (CWP 5.3). If this is valid for vector's why not any other
templated class with a swap member function?

namespaces are open, therefore almoost anything can be put into
namespace std, but its not standard to polute the std namespace.

alan_gr...@my-deja.com

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
In article <fl66ugp...@pizza.cmla.ens-cachan.fr>,

Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
>
> As unrealistic as to require every author of template library to learn
> about template and the two-phase name lookup mechanics (or at least to
> be competent)?

But it is not just authors of template libraries that are affected. (I
might not like the situation - but at least you and I understand it.) On
this thread there has been an example of the problem impacting code
maintenance in a non-template class, and a people indicating the desire
that typing in client code std::swap resolve to the "correct" version.

IMO if the library working group had understood the implications of the
current rules then they would have supplied a standard implementation of
the forwarding non-member function templates.

I admit that allowing overloading of the standard algorithms (such as
swap<>) based on a user defined name does have theoretical problems.
For example, if we allow:


// No _I_ wouldn't put it in global namespace - but bear with me
template<typename element>
class heap;

namespace std {
template<typename element>
swap(heap<element>&, heap<element>&) { ... }
}

What happens when the committee decides to add std::heap in a future
version of C++?

There is a problem - you have taken the reasonable position that the
resolution is by education. I don't believe that is adequate.


-
Alan Griffiths (alan.gr...@experian.com, +44 115 934 4517)
Senior Systems Consultant, Experian


Sent via Deja.com http://www.deja.com/
Before you buy.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Siemel B. Naran

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
On 21 Mar 2000 11:50:41 -0500, Gabriel Dos Reis

>Not if you just said:
>
> swap(v1, v2);
>

>Koenig lookup will take care of you.

Good.


>Writing "std::swap" is strong a requirement -- as any form of
>qualified-id use. If you want flexible programms, then you have to be
>flexible in your requirements.

Good.


If the builtin types lived in namespace std then I would agree with
you 100%. But at the present time, I agree with you 96%.

namespace enhanced {
template <class Iter>
void rapidsort(Iter begin, Iter end) { /*use swap(*begin,*end)*/ }
}

If Iter::value_type is any type in namespace std, then the call to
swap(*begin,*end) automatically looks in namespace std for the
definition of swap and finds it.

If Iter::value_type is any type in namespace myspace and we have
taken care to declare myspace::swap(...), then the call to
swap(*begin,*end) automatically looks in namespace myspace for the
definition of swap and finds it.

But if Iter::value_type is a fundamental type, then the unqualified
call to swap(*begin,*end) fails to find the declaration of swap.


Solution 1: Define the fundamental types (double, int, ...) in
namespace std.

Solution 2: Define explicit functions ::swap(int,int), etc.

--
--------------
siemel b naran
--------------

Siemel B. Naran

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
On 22 Mar 2000 09:50:17 -0500, alan_gr...@my-deja.com

>A better example (because it prevents Gabriel's solution) is:
>
> struct example
> {
> std::vector<int> v;
>
> void swap(example& that) // Swap this and that
> {
> std::swap(v, that.v); // OK
> }
> };

The "std::" is not necessary and ill-advised.
Koenig lookup says to look in the namespace where "this->v" and
"that.v" live to find the definition of swap. This namespace is
"std::".

Siemel B. Naran

unread,
Mar 23, 2000, 3:00:00 AM3/23/00
to
On 23 Mar 2000 04:11:11 -0500, Carl Barron <cbar...@ix.netcom.com> wrote:
>Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:

>> But as I said in another message
>>
>> template<typename T>
>> void swap(P<T>&, P<T>&) { /* ... */ }
>>
>> is *not* a partial specialization. It is an overloading. Thus

>> it cannot be put in namespace std, as per the rule quoted above.

> Well what does your <vector> file do to define swap for vectors??
> I'd bet it says something like:
>
> template <class T,class A>
> void swap(vector<T,A> &,vector<T,A> & y) {x.swap(y);}
>
> mine does (CWP 5.3). If this is valid for vector's why not any other
>templated class with a swap member function?

It is not necessary to put the definition of swap in namespace std,
thanks to Koenig lookup. Just do

namespace enhanced {
template <class T> class Matrix { ... };
template <class T>
void swap(Matrix<T>& lhs, Matrix<T>& rhs) { lhs.swap(rhs); }
}

int main() { enhanced::Matrix<int> M1,M2; swap(M1,M2); }

The call to swap looks in the namespace where M1 and M2 live for the
definition of swap. Thus it finds enhanced::swap(...).


> namespaces are open, therefore almoost anything can be put into
>namespace std, but its not standard to polute the std namespace.

The rule that you ought not to put your specializations in namespace
std is good because it's not good to open up someone else's library
and fiddle around with it. As the author of namespace enhanced, I
forbid anyone to specialize any of my classes.


But the other question remains -- what is the difference between a
template specialization and overloading? To my mind, they really
are the same thing.

Darin Adler

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
In article <1e7so19.jw...@buf-ny10-99.ix.netcom.com>,
cbar...@ix.netcom.com (Carl Barron) wrote:

> Well what does your <vector> file do to define swap for vectors??
> I'd bet it says something like:
>
> template <class T,class A>
> void swap(vector<T,A> &,vector<T,A> & y) {x.swap(y);}
>
> mine does (CWP 5.3). If this is valid for vector's why not any other
> templated class with a swap member function?

Because vector is part of the standard library. This specialization is
required by the standard. That doesn't guarantee that you can do it for
your own classes.

> namespaces are open, therefore almoost anything can be put into
> namespace std, but its not standard to polute the std namespace.

I don't know what you mean when you say it "can be put" in std. Yes, the
compiler and library you have might allow it, and it might have
predictable behavior. But the standard explicitly forbids it, so it
isn't guaranteed to work at all with other compilers or library
implementations.

-- Darin

Darin Adler

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
In article <8bd2o7$j1h$1...@nnrp1.deja.com>, alan_gr...@my-deja.com
wrote:

> I admit that allowing overloading of the standard algorithms (such as
> swap<>) based on a user defined name does have theoretical problems.
> For example, if we allow:
>
> // No _I_ wouldn't put it in global namespace - but bear with me
> template<typename element>
> class heap;
>
> namespace std {
> template<typename element>
> swap(heap<element>&, heap<element>&) { ... }
> }
>
> What happens when the committee decides to add std::heap in a future
> version of C++?

This can be resolved; unfortunately, it's "by education" also:

template<typename element>
class heap;

namespace std {
template<typename element>

swap(::heap<element>&, ::heap<element>&) { ... }
}

You've got to be on your best behavior when visiting namespace std.

Lisa Lippincott

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Alan Griffiths <alan_gr...@my-deja.com> volunteers:
> I'm not the only one that knowingly relies on "undefined behavior" in
> this area - check out the boost smart pointers (http://www.boost.org/).
> AFAIK there is no ideal solution in the language as currently defined.
> When I can work out what the standard should say I'll submit a defect
> report. (But this isn't easy either.)

I'll give you a push. Here's the insufficient part of the standard,
from 17.4.3.1 [lib.reserved.names]:

A program may add template specializations for any standard
library template to namespace std. Such a specialization
(complete or partial) of a standard library template results
in undefined behavior unless the declaration depends on a
user-defined name of external linkage and unless the specialization
meets the standard library requirements for the original template.

To me, the limits provided by this passage seem adequate for overloading.
I suggest adding:

A program may add to namespace std function template declarations
which overload any standard library function template name. Such
declarations result in undefined behavior unless the declaration
depends on a user-defined name of external linkage and unless the
function template meets the standard library requirements for
the original template.

More boldly, I suggest allowing overloading for non-template functions
as well. This would be a real boon in numeric programming, allowing
the function names in 26.5 [lib.c.math] to be used for user-defined
numeric types, in addition to int, long, float, and double.

Here's a more expansive wording:

A program may add to namespace std function or function template
declarations which overload any standard library function or
function template name. Such declarations result in undefined
behavior unless the declaration depends on a user-defined name of
external linkage and unless the function or function template
meets the standard library requirements for the original function
or function template.

Since a careful programmer will use a fully-qualified "user-defined name
of external linkage," lest it become standard-defined in the future.
It may be a good idea to add that adjective to both the old and the new
wording.

How does this wording sound?
--Lisa Lippincott

Andrei Alexandrescu

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Siemel B. Naran <sbn...@uiuc.edu> wrote in message
news:slrn8dkbp5....@localhost.localdomain...

[snip all]

You are 96% happy, but I'm still not satisfied.

My question is: what's easier?

1. Give someone a library and just ask them to call std algorithms with the
objects of your types as they always did. That is, you define a class BigNum
and they can call std::swap(a, b) for a and b being two BigNums. I find this
a simple and intuitive rule.

2. Give someone a library and tell them they must use the following idiom:

{
BigNum a;
using std::some_algorithm;
some_algorithm(a);
}

in *every* darn place they ever use a standard algorithm on any of your
types.

I don't think you can convince me easily that (2) is preferrable.

What's worse about (2) is that, in particular for swap, reckless users will
not be flagged by the compiler. If BigNum has value semantics (as it
should), then std::swap will work on it, but very inefficiently.

Now we live in a wonderful world:

a) Savvy users will use the correct, verbose, ugly, deplorable, hateable
idiom (2) and will get efficient programs.

b) Plebeian users (as I have to humbly submit I am - I always thought you
can and should overload std::algorithms for your types appropriately) will
write code that uses std::swap explicitly, the compiler will not say a
thing, and their programs will work, but slower.

Same story goes about, for instance, std::copy. If a library defines a POD
and a bit-blasting copy in that library's namespace, users who call
std::copy on pointers to those PODs will get the program working, only
slower.

I find this sad. I'm not a namespace expert, and now that I discovered some
details I'd say, ignorance is bliss.

There's one more thing I don't like about this thread - the attitude that
the Standard is perfect and that any criticism to it is an insult. I don't
like being a yesman. I don't like how namespaces work, and you cannot prove
me how nice they are just because they are standard. It just happens, even
some of the people who helped with *defining* namespaces don't like how they
work and admit they are... here degree of appreciation varies from imperfect
to flawed to broken.


Andrei

Gabriel Dos Reis

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
alan_gr...@my-deja.com writes:

| In article <fln1ntu...@pizza.cmla.ens-cachan.fr>,


| Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:

| > Thomas Maeder <mae...@glue.ch> writes:
| >
| > | Gabriel Dos Reis schrieb:
| > | >
| > | > Why can't you put 'swap(Matrix<>&, Matrix<>&)' in Matrix's
| namespace
| > | > definition?
| > |
| > | Because the option of specializing Standard library classes and
| functions
| > | was ruled in to provide compile-time specialization.
| > |
| > | Say I have this program:
| > |
| > | int main()
| > | {
| > | std::vector<int> v1,v2;
| > | // initialization of v1 and v2
| > |
| > | std::swap(v1,v2); // ok
| > | }
|

| A better example (because it prevents Gabriel's solution) is:
|
| struct example
| {
| std::vector<int> v;
|
| void swap(example& that) // Swap this and that
| {
| std::swap(v, that.v); // OK
| }
| };
|
| > |

| > | If I then decide to substitute a container class template of my own
| for
| > | std::vector, I have to change the call to swap, too.
|
| Exactly.
|

| > Not if you just said:
| >
| > swap(v1, v2);
|

| In the revised example name lookup only finds example::swap() - which
| causes a compile error.

Could you explain why?


3.4.2/2 implies that lookup will find std::swap.

| > Koenig lookup will take care of you.
|

| Not in the revised example.

Even in the revised example. Or you have to revise your revised
example :-)

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gabriel Dos Reis

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
Jonathan Lundquist <j...@sssonline.com> writes:

| On 20 Mar 2000 05:50:16 -0500, Gabriel Dos Reis


| <dos...@cmla.ens-cachan.fr> wrote:
|
| >
| >But as I said in another message
| >
| > template<typename T>
| > void swap(P<T>&, P<T>&) { /* ... */ }
| >
| >is *not* a partial specialization. It is an overloading. Thus

| >it can be put put in namespace std, as per the rule quoted above.
|
| Whatever we call that thing above, can anyone give a good reason why
| it isn't allowed in std (besides the standard says so). Is there any
| scenario where ambiguities arise provided 'P' is a user defined
| template? Is this an oversight in the standard?

I think the rationale is that any name found by lookup in std:: is
guaranteed to be defined either by the standard or the implementation
(this expresses the reserved nature of std).

But I wasn't there when that rule was voted in.

Gabriel Dos Reis

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
alan_gr...@my-deja.com writes:

| In article <fl66ugp...@pizza.cmla.ens-cachan.fr>,


| Gabriel Dos Reis <dos...@cmla.ens-cachan.fr> wrote:
| >

| > As unrealistic as to require every author of template library to learn
| > about template and the two-phase name lookup mechanics (or at least to
| > be competent)?
|
| But it is not just authors of template libraries that are affected. (I
| might not like the situation - but at least you and I understand it.) On
| this thread there has been an example of the problem impacting code
| maintenance in a non-template class, and a people indicating the desire
| that typing in client code std::swap resolve to the "correct" version.

I do understand the desire to overload function template in std.
But I think the main issue is user education. I think they got there
because of a particular design of their program. The first thing we
need to address is whether that design can be corrected.

| IMO if the library working group had understood the implications of the
| current rules then they would have supplied a standard implementation of
| the forwarding non-member function templates.
|

| I admit that allowing overloading of the standard algorithms (such as
| swap<>) based on a user defined name does have theoretical problems.

But we need to reserve a namespace for future extension. One simple
way to acheive that is to put in a rule that guarantee that any name
found by lookup in std:: is defined either by the standard or the
implementation. That is what the current rule does.

| For example, if we allow:
|
|
| // No _I_ wouldn't put it in global namespace - but bear with me
| template<typename element>
| class heap;
|
| namespace std {
| template<typename element>
| swap(heap<element>&, heap<element>&) { ... }
| }
|
| What happens when the committee decides to add std::heap in a future
| version of C++?
|

| There is a problem - you have taken the reasonable position that the
| resolution is by education. I don't believe that is adequate.

Well, I think this is a topic on which reasonable people can disagree.
And I do understand your point of view. I just happen to be
unconvinced that the rule should be changed.

Gabriel Dos Reis

unread,
Mar 24, 2000, 3:00:00 AM3/24/00
to
nik...@my-deja.com writes:

[...]

| >
| > Now, partial ordering (14.5.5.2) says that the function template
| >
| > template<typename T> swap(MyType<T>&, MyType<T>&)
| >
| > is more specialized than
| >
| > template<typename T> swap(T&, T&)
| >
| > so swap<int>(MyType<T>&, MyType<T>&) should be selected.
| >
| > Am I overlooking something?
|
| This is the part I'm questioning, but I don't really understand
| the partial ordering rules so I may be wrong. Let me try to
| break it down into steps.
|
| Section 14.5.5.2 paragraphs 2-3 say the two function templates
| are transformed as follows:
|
| ; Replace T with MyType<int> in first template.
| swap(MyType<int>&, MyType<int>&);
|
| ; Replace T with int in second template.
| swap(MyType<int>&, MyType<int>&);

No. That is not what 14.5.5.2/[2-3] say.
Consider:
1) template<typename T> void swap(T&, T&);
2) template<typename T> void swpa(MyType<T>&, MyType<T>&)

In the first template, replace T with unique_type (where unique_type
is a unique type). Now attempt template argument deduction for the
second template against the parameter list (unique_type&, unique_type&).
That argument deduction fails. So the first template is *not* at
least as specialized as the second.

Repeat the same process in the reverse way. Here argument deduction
for the first template against (MyType<unique_type>&, MyType<unique_type>&)
succeeds. So the second template is at least as specialized as the
first. It follows from 14.5.5.2/5 that the second template is more
specialized than the first. So swap<int>(MyType<int>&, MyType<int>&)
is selected.

[...]

| I realize examples are non-normative, but the example in
| this section seems to reinforce the above analysis:
|

| ...


| template<class T> void h(const T&);
| template<class T> void h(A<T>&);
| ...
| h(z); // overload resolution selects h(A<T>&)
| ...
|
| The comment implies that neither function template is
| "more specialized" than the other;

Right.

| ... the call would be


| amgiguous except that overload resolution selects the
| function that takes a non-const reference.

This is just an example where partial ordering that doesn't help
because not applicable.

|
| > | Because of this, I mistakenly asserted that the two functions
| > | are not overloaded. It would be more accurate to say that
| > | overloading doesn't solve my problem. That problem once
| > | again is:
| > |

| > | How can I write a swap function for my template class
| > | in such a way that my function will always be called
| > | instead of the general-purpose std::swap function.
| >
| > Just put it in the namespace of your class template definition.
|

| But will Koenig lookup find my version of swap if the caller
| uses an explicit namespace qualifer as in the above example?

No. Koenig lookup works only for unqualified-id.

Darin Adler

unread,
Mar 25, 2000, 3:00:00 AM3/25/00
to
In article <230320001820066212%lisa_li...@bigfix.com>, Lisa
Lippincott <lisa_li...@bigfix.com> wrote:

> How does this wording sound?

Sounds great to me.

But the more expansive version that allows overloading even non-template
functions seems that it could be a bit dangerous and I suggest we omit
that if submitting a defect report. Howard Hinnant at Metrowerks may
have some wisdom to impart about his experiences with overloading and
<math.h>; I seem to recall that adding additional signatures created all
sorts of strange incompatibilities.

-- Darin