[array] change proposal for the c_array() function

Hi, I'm new in this mailing list .My interest are embedded software and code reuse. I would submit a simple change request in the boost::array library. The boost::c_array() function is expected to cast a boost::array<T,N> into a C-array but actually the returned type is a T* which is not exactly a reference on a C-array. to keep track of the static size and make sizeof( myarray.c_array() ) returning the real size of the C-array, I suggest to change: T* c_array() { return elems; } into T (&c_array())[N] { return *(T(*)[N]) elems; } by the way, I have developed a function helper array_cast<> whose purpose is to: * make a bit more friendly the syntax when casting to a C-array * check consistency between size of the input type and size of the target C-array for example, { long titi; char (&test)[4] = utils::array_cast<char>( titi ); test[0] = 0; } assuming that long is 32 bit long and char is 8 bit long, 'test[0]' is now a reference on the 1st byte of 'titi'. Moreover declaring test as a char(&)[5] would have failed in compiling since size of both types are not suitable (but the function provides some other way to force cast when sizes are not compatible) do you think that there could be any interest to include this function in boost library ? thanks, herve

herve martin wrote:
I would submit a simple change request in the boost::array library. ... I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
Believe it or not, I was considering to submit the very same feature request. But go ahead: https://svn.boost.org/trac/boost/newticket (Please consider requesting a const overload as well!) Actually I did the very same request for std::array! But apparently the C++ Library Working Group considers a different resolution, adding explicit conversion operators instead, converting an std::array to a reference to its built-in array: http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#930 BTW, Nicolai Josuttis, the author of boost::array, told me that c_array() is only there for historical reasons.
I have developed a function helper array_cast<> whose purpose is to: * make a bit more friendly the syntax when casting to a C-array * check consistency between size of the input type and size of the target C-array
for example, { long titi; char (&test)[4] = utils::array_cast<char>( titi );
test[0] = 0; } assuming that long is 32 bit long and char is 8 bit long, 'test[0]' is now a reference on the 1st byte of 'titi'. Moreover declaring test as a char(&)[5] would have failed in compiling since size of both types are not suitable (but the function provides some other way to force cast when sizes are not compatible)
I'm interested to know if such an array_cast function could be made platform independent and safe with respect to byte alignment. Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

herve martin wrote:
I would submit a simple change request in the boost::array library. ... I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
No need to change the original implementation of array::c_array()! Your change of its return type should be sufficient: T (&c_array())[N] { return elems; }
Actually I did the very same request for std::array! [...] http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#930
Kind regards, Niels

Niels Dekker - mail address until 2010-10-10 wrote:
herve martin wrote:
I would submit a simple change request in the boost::array library. ... I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
No need to change the original implementation of array::c_array()! Your change of its return type should be sufficient:
T (&c_array())[N] { return elems; }
Why not simply accessing elems directly? It's public.

No need to change the original implementation of array::c_array()! Your change of its return type should be sufficient: T (&c_array())[N] { return elems; }
Andrey Semashev wrote:
Why not simply accessing elems directly? It's public.
It looks like it's indeed okay to access boost::array::elems directly. But tr1::array::elems is marked as "Exposition only". Other TR1 implementations have indeed named their tr1::array data member differently. Unfortunately c_array() is also specific to Boost. So I've proposed to add this member function to std::array as well (LWG issue #930), returning a reference to the array. (Including overloads for const and rvalue arrays.) Kind regards, Niels

Niels Dekker wrote:
No need to change the original implementation of array::c_array()! Your
change of its return type should be sufficient: T (&c_array())[N] { return elems; }
You are completely right !
Andrey Semashev wrote:
Why not simply accessing elems directly? It's public.
It looks like it's indeed okay to access boost::array::elems directly. But tr1::array::elems is marked as "Exposition only". Other TR1 implementations have indeed named their tr1::array data member differently.
Unfortunately c_array() is also specific to Boost. So I've proposed to add this member function to std::array as well (LWG issue #930), returning a reference to the array. (Including overloads for const and rvalue arrays.)
I argue that c_array() function does not do what we could implicitly expect from it regarding its name. A C array type encapsulates a pair of information: its size and its elements type. I guess it's a shame to break this pair as we usually do. BTW, a reference on array is implicitly convertible into a pointer on its 1st element. So the change would be really minor. This following lines of code would still work: { array<int,10> toto; int* item_ptr = toto.c_array(); } As far as I can see, the only improvement which would be brought by the change is that sizeof( toto.c_array() ) would return value 10*sizeof(int), the real size of the C array. About the array_cast() I will open an other thread. I'm working also on an array_ref<T,N> class template which exports quite the same interface as a boost::array and wraps a reference on C array. The main purpose is to allow an existing C array to be used as a STL sequence container. If I can convince about the benefit of these 2 new features, I guess it would be nice to add them into the existing boost array package as in my point of view the boost::array class, array_ref class and array_cast function create a consistent unit. best regards, herve

Niels Dekker wrote:
herve martin wrote:
I would submit a simple change request in the boost::array library.
...
I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
Believe it or not, I was considering to submit the very same feature request. But go ahead: https://svn.boost.org/trac/boost/newticket (Please consider requesting a const overload as well!)
maybe I'm wrong but I don't think that we need the const overload since a T(&)[N] is implicitly convertible into a const T(&)[N] so { const int (&toto)[10] = (new boost::array<int,10>)->c_array() } should work. best regards, herve

herve martin wrote:
Niels Dekker wrote:
herve martin wrote:
I would submit a simple change request in the boost::array library.
...
I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
Believe it or not, I was considering to submit the very same feature request. But go ahead: https://svn.boost.org/trac/boost/newticket (Please consider requesting a const overload as well!)
maybe I'm wrong but I don't think that we need the const overload since a T(&)[N] is implicitly convertible into a const T(&)[N] so { const int (&toto)[10] = (new boost::array<int,10>)->c_array() } should work.
Woudn't you need a const overload of c_array, if the original array is const? Or you only have a const reference to it? Bo Persson

on Sat Mar 14 2009, herve martin <hervemart1-AT-gmail.com> wrote:
Hi,
I'm new in this mailing list .My interest are embedded software and code reuse.
I would submit a simple change request in the boost::array library. The boost::c_array() function is expected to cast a boost::array<T,N> into a C-array but actually the returned type is a T* which is not exactly a reference on a C-array.
to keep track of the static size and make sizeof( myarray.c_array() ) returning the real size of the C-array, I suggest to change: T* c_array() { return elems; }
into T (&c_array())[N] { return *(T(*)[N]) elems; }
Looks good in principle. What is the status of that function in TR1 and the latest draft standard? If it is different from your proposal, we should probably think about the consequences. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Herve Martin wrote:
I suggest to change: T* c_array() { return elems; } into T (&c_array())[N] { return *(T(*)[N]) elems; }
David Abrahams wrote:
Looks good in principle. What is the status of that function in TR1 and the latest draft standard? If it is different from your proposal, we should probably think about the consequences.
Hi Herve, David and I just mailed about the issue and we agreed that it would be preferable to have such a function as a non-member. Because tr1::array doesn't have such a c_array() member function and std::array probably won't have one either. Such a boost::get_c_array(arg) function (template) could be overloaded to support both std::array and boost::array. For details, please have a look at https://svn.boost.org/trac/boost/ticket/2857#comment:2 HTH, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center
participants (6)
-
Andrey Semashev
-
Bo Persson
-
David Abrahams
-
herve martin
-
Niels Dekker - address til 2010-10-10
-
Niels Dekker - mail address until 2010-10-10