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:
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.
> 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:
> 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...
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.
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:
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.
>> 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.
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)?
In article <47BFFB3D.5D59C...@this.is.invalid>, Niels Dekker - no
return address <nore...@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.
[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?
> 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:
> 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.
<cbarron...@adelphia.net> wrote: > In article <47C1E8A5.BE218...@this.is.invalid>, Niels Dekker - no > return address <nore...@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)}
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.