Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Standard Library] Shouldn't std::swap be overloaded for C-style arrays?

344 views
Skip to first unread message

Niels Dekker - no return address

unread,
Feb 22, 2008, 12:43:00 PM2/22/08
to
For the sake of generic programming, I think that std::swap should be
overloaded for C-style arrays. It could be implemented as follows:

namespace std {
template <typename T, size_t N>
void swap(T (&lhs)[N], T (&rhs)[N]) {
swap_ranges(lhs + 0, lhs + N, rhs);
}
}

Don't you think so too?

Background:

I was considering adding swap functions to a wrapper class template. In
fact
I had boost::value_initialized in mind, but let's assume that the
wrapper is
simply called W, and defined as follows:

template <typename T>
class W {
public:
T data;
};

By definition, both W<int[8]> and W<std::vector<int> > are Swappable,
because they are both CopyConstructible and CopyAssignable. Still for the
sake of efficiency and exception safety, I was considering adding the
following swap function to the namespace of W:

template <typename T>
void swap(W<T> & lhs, W<T> & rhs) {
using std::swap;
swap(lhs.data, rhs.data);
}

Note that I'm doing "using std::swap" here, to get the most appropriate
swap
function, as recommended by Scott Meyers' Effective C++, 3rd Edition, item
25, "Consider support for a non-throwing swap".

Unfortunately, after adding this swap function, the following would no
longer compile:

int main() {
W<int[8]> w1, w2;
using std::swap;
swap(w1, w2);
}

The problem would be fixed by providing an overload of std::swap for
C-style
arrays. Moreover, if this overload would be implemented in terms of
swapping the elements of the array, it would be non-throwing for those
element types that have a non-throwing swap.

Your feedback is appreciated...

Kind regards,
--
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
Scientific programmer at LKEB, Leiden University Medical Center

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Carl Barron

unread,
Feb 23, 2008, 1:14:39 AM2/23/08
to
In article <47becc92$0$14358$e4fe...@news.xs4all.nl>, Niels Dekker -

I see no gain adding this as boost/tr1 array is very little weight and
provides needed info includiing a swap member function. its either a
misprint but I did not see a free function swap overload for array<T,N>
but, its easy to write if its missing.

--

Greg Herlihy

unread,
Feb 23, 2008, 1:14:38 AM2/23/08
to
On Feb 22, 9:43 am, "Niels Dekker - no return address"

<nore...@this.is.invalid> wrote:
> For the sake of generic programming, I think that std::swap should be
> overloaded for C-style arrays. It could be implemented as follows:
>
> namespace std {
> template <typename T, size_t N>
> void swap(T (&lhs)[N], T (&rhs)[N]) {
> swap_ranges(lhs + 0, lhs + N, rhs);
> }
> }
>
> Don't you think so too?

Not really. Adding new functions for C-style arrays in the next C++
Standard would likely have the unfortunate effect of encouraging C++
programmers to continue to use those kinds of arrays in their
programs.

In my view, the next C++ Standard would better serve C++ programmers -
not by enhancing the appeal of C-style arrays - but rather by
promoting the adoption of their equally efficient - but safer
replacement - the C++ "std::array". Moreover, std::array - exactly as
one would expect of a C++ Standard Library class template - does
implement a swap() method.

Greg

--

Niels Dekker - no return address

unread,
Feb 23, 2008, 6:13:13 AM2/23/08
to
>> For the sake of generic programming, I think that std::swap should
>> be overloaded for C-style arrays.

Carl Barron wrote:
> I see no gain adding this as boost/tr1 array is very little weight

> and provides needed info including a swap member function.

Thanks for your reply. So are you saying that with the introduction of
boost/tr1 array, the Standard Library does no longer need to support the
use of C-style arrays? And do you think that a generic wrapper template
class like boost::value_initialized<T> should not support C-style arrays
as template argument?

> its either a misprint but I did not see a free function swap overload
> for array<T,N> but, its easy to write if its missing.

Fortunately it is there in the latest Working Draft,
<http:://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2521.pdf>:

23.2.1.2 array specialized algorithms [array.special]

template <class T, size_t N>
void swap(array<T,N>& x, array<T,N>& y);
Effects:
swap_ranges(x.begin(), x.end(), y.begin() );

But still I think that std::swap should support C-style arrays as well.
Howard Hinnant already wrote to me that he can make it an issue for the
Library Working Group (LWG). :-) One more technical question, though.
In my previous posting I suggested implementing an std::swap overload
for C-style arrays as follows:

template <typename T, size_t N>
void swap(T (&lhs)[N], T (&rhs)[N]) {
swap_ranges(lhs + 0, lhs + N, rhs);
}

Do you know if this addition of zero, "lhs + 0", is really necessary (to
make sure that the first and the second argument are of the same type)?
If so, should the third argument passed to swap_ranges also have an
addition of zero, "rhs + 0" (to make sure that the third argument is a
ForwardIterator)?

Kind regards, Niels

Jeff Schwab

unread,
Feb 23, 2008, 11:45:32 AM2/23/08
to
Carl Barron wrote:

> I did not see a free function swap overload for array<T,N>

6.2.2.2 array specialized algorithms [tr.special.array]

template <class T, size_t N> void swap(array<T,N>& x, array<T,N>& y);

Effects:
swap_ranges(x.begin(), x.end(), y.begin() );

--

Carl Barron

unread,
Feb 24, 2008, 4:41:09 AM2/24/08
to
In article <47BFFB3D...@this.is.invalid>, Niels Dekker - no
return address <nor...@this.is.invalid> wrote:

> Carl Barron wrote:
> > I see no gain adding this as boost/tr1 array is very little weight
> > and provides needed info including a swap member function.
>
> Thanks for your reply. So are you saying that with the introduction of
> boost/tr1 array, the Standard Library does no longer need to support the
> use of C-style arrays? And do you think that a generic wrapper template
> class like boost::value_initialized<T> should not support C-style arrays
> as template argument?

I think that because boost/tr1 array is a very light weight class ,
it can be implemented with the same footprint as an C-array and provide
type safety and works with <algorithm> most of the member functions of
array are simple enough to inline almost always as they are just access
the data in the array it holds or its size which is part of its type
and a compile time constant.


>
> Fortunately it is there in the latest Working Draft,
> <http:://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2521.pdf>:

Thanks, replacing my draft...

If there is a simple fix fine, let the working group fix it. But I
think the array depreciation to ptr will kick in....

Niels Dekker - no return address

unread,
Feb 25, 2008, 1:07:36 AM2/25/08
to
[Don't you think std::swap be overloaded for C-style arrays?]

Greg Herlihy repied:


> Not really. Adding new functions for C-style arrays in the next C++
> Standard would likely have the unfortunate effect of encouraging C++
> programmers to continue to use those kinds of arrays in their
> programs.
>
> In my view, the next C++ Standard would better serve C++ programmers -
> not by enhancing the appeal of C-style arrays - but rather by
> promoting the adoption of their equally efficient - but safer
> replacement - the C++ "std::array". Moreover, std::array - exactly as
> one would expect of a C++ Standard Library class template - does
> implement a swap() method.

I'm sorry I haven't convinced you. [ Note that your posting hasn't yet
appeared on some news servers, including news.astraweb.com and
news.xs4all.nl. Luckily I found it at
http://groups.google.com/group/comp.lang.c++.moderated ] So would you
never use C-style arrays anymore? AFAIK, they still have a feature that
the "std::array" won't have. When initializing a C-style array, you
don't need to explicitly specify its number of elements:
int x[] = { 1, 3, 5 }; // Okay (of course).
array<int> y = { 1, 3, 5 }; // Invalid, isn't it?

Anyway, please take another look at my wrapper example:

// Wrapper:


template <typename T>
class W {
public:
T data;
};

// Its swap function:


template <typename T>
void swap(W<T> & lhs, W<T> & rhs) {
using std::swap;
swap(lhs.data, rhs.data);
}

W<int[8]> is Swappable, but an attempt to swap two instances of
W<int[8]> would be rejected by the compiler:

W<int[8]> w1, w2; // So w1 and w2 are Swappable.
swap(w1, w2); // Rejected!

I think that's an inconsistency that should be fixed.

Carl Barron wrote:
[...]


> If there is a simple fix fine, let the working group fix it.

Thanks :-) I think that overloading std::swap for C-style arrays is
reasonably simple.

> But I think the array depreciation to ptr will kick in....

Can you please explain what specific depreciation you're referring to?


Kind regards,

Niels

Carl Barron

unread,
Feb 25, 2008, 7:06:34 AM2/25/08
to
In article <47C1E8A5...@this.is.invalid>, Niels Dekker - no
return address <nor...@this.is.invalid> wrote:

>
> Carl Barron wrote:
> [...]
> > If there is a simple fix fine, let the working group fix it.
>
> Thanks :-) I think that overloading std::swap for C-style arrays is
> reasonably simple.
>
> > But I think the array depreciation to ptr will kick in....
>
> Can you please explain what specific depreciation you're referring to?
>
>
> Kind regards,

not sure of exact ordering but array names are converted to pointers
when passed as arguments to functions.

Sebastian Karlsson

unread,
Feb 25, 2008, 5:16:15 PM2/25/08
to
{ Please remove the banner from your quotation. -mod }


On 23 Feb, 07:14, Greg Herlihy <gre...@mac.com> wrote:
> On Feb 22, 9:43 am, "Niels Dekker - no return address"
>
> <nore...@this.is.invalid> wrote:
> > For the sake of generic programming, I think that std::swap should be
> > overloaded for C-style arrays. It could be implemented as follows:
>
> > namespace std {
> > template <typename T, size_t N>
> > void swap(T (&lhs)[N], T (&rhs)[N]) {
> > swap_ranges(lhs + 0, lhs + N, rhs);
> > }
> > }
>
> > Don't you think so too?
>
> Not really. Adding new functions for C-style arrays in the next C++
> Standard would likely have the unfortunate effect of encouraging C++
> programmers to continue to use those kinds of arrays in their
> programs.
>
> In my view, the next C++ Standard would better serve C++ programmers -
> not by enhancing the appeal of C-style arrays - but rather by
> promoting the adoption of their equally efficient - but safer
> replacement - the C++ "std::array". Moreover, std::array - exactly as
> one would expect of a C++ Standard Library class template - does
> implement a swap() method.
>
> Greg

While I also think C++ data structures should be encourage the reality
unfourtualy still is that A LOT of libraries have only C interfaces
because of compability, and I don't see that changing in the near
future.

Carl Barron

unread,
Feb 26, 2008, 2:19:10 AM2/26/08
to
In article <250220080256293994%cbarr...@adelphia.net>, Carl Barron
<cbarr...@adelphia.net> wrote:

> In article <47C1E8A5...@this.is.invalid>, Niels Dekker - no
> return address <nor...@this.is.invalid> wrote:
>
> >
> > Carl Barron wrote:
> > [...]
> > > If there is a simple fix fine, let the working group fix it.
> >
> > Thanks :-) I think that overloading std::swap for C-style arrays is
> > reasonably simple.
> >
> > > But I think the array depreciation to ptr will kick in....
> >
> > Can you please explain what specific depreciation you're referring to?
> >
> >
> > Kind regards,
> not sure of exact ordering but array names are converted to pointers
> when passed as arguments to functions.

FYI - you can with the help of the preprocessor and a slightly
different syntax of the intiailization create a boost/tr1 array where
the compiler computes the size of the array. Here is a test version
to show the idea.
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>

#define SEQ (1)(2)(3)

#define ARRAY_MACRO(R,D,E) E,

//BOOST_PP_SEQ_FOR_EACH(ARRAY_MACRO,_,SEQ)

#define MAKE_ARRAY(TYPE,NAME,INIT)\
boost::array<TYPE,BOOST_PP_SEQ_SIZE(INIT)>\
NAME = { BOOST_PP_SEQ_FOR_EACH(ARRAY_MACRO,_,\
INIT)}


#if 0
#include <boost/array.hpp>
#endif

MAKE_ARRAY(int,a,SEQ);

MAKE_ARRAY(int,b,(1)(2)(3));

#undef ARRAY_MACRO

Niels Dekker - no return address

unread,
Feb 26, 2008, 2:48:16 AM2/26/08
to
Carl Barron wrote:
>>> But I think the array depreciation to ptr will kick in....
>> Can you please explain what specific depreciation you're referring
>> to?
> not sure of exact ordering but array names are converted to pointers
> when passed as arguments to functions.

Okay, so you mean *decay*! (You got me confused, because of the special
meaning of "depreciated" within the C++ Standard.) I don't think
array-to-pointer decay will kick in when passing two arrays to
std::swap. And it still wouldn't kick in when an overload for C-style
arrays would be added to the std namespace:

template <typename T, size_t N>

void swap(T (&lhs)[N], T (&rhs)[N]);

I just double-checked section 14.8.2.1, Deducing template arguments from
a function call [temp.deduct.call], from the Draft (N2521). It *only*
says that array-to-pointer conversion is applied to an argument if the
corresponding function template parameter type (P) is *not* a reference
type. But in the case of std::swap, both of the function template
parameters (lhs, rhs) are references. So in this case, array-to-pointer
convertion is not applied, during template argument deduction.


Kind regards, Niels

Niels Dekker - no return address

unread,
Mar 25, 2008, 3:13:48 PM3/25/08
to
> For the sake of generic programming, I think that std::swap should
> be overloaded for C-style arrays. It could be implemented as follows:
>
> namespace std {

> template <typename T, size_t N>
> void swap(T (&lhs)[N], T (&rhs)[N]) {
> swap_ranges(lhs + 0, lhs + N, rhs);
> }
> }

For the record, my request for such an std::swap overload is indeed added to
the list of C++ Standard Library issues. :-)

LWG issue 809: std::swap should be overloaded for array types
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#809

Thanks to Howard Hinnant,

0 new messages