I think the initializer_list overloads may be unnecessary, and turn what should be a compile-time arity check to a runtime assertion on size(). They could help to support very high dimensionality, higher than the maximum supported number of function arguments, but I don't think most relevant platforms actually have such a limitation, and low dimensionality could be penalized by adding the overhead of the pointers and "hard" stack allocation.
Another approach would be to make std::multi_array an alias template to a nested std::array type. The multidimensional accessor overloads could be added to one-dimensional std::array and delegate recursively to the underlying type. This would support existing code which nests std::array, or even other numeric libraries inside std::array (which I have done with Eigen; there are advantages to this and practical use cases). It would incur nonsense semantics for operator() on an array over a type with well-defined operator() ( std::size_t [, std::size_t … ] )— but that's a corner case, and array::operator() isn't so far defined anyway. The interface and implementation would be more lightweight.
When was the last time n-adic operator[] support was considered? Doesn't the potential use in the scientific arena outweigh the need to support abuse of the comma operator inside square brackets? C'mon, let's deprecate that syntactic sucker.
On Friday, September 6, 2013 9:58:30 PM UTC-4, David Krauss wrote:I think the initializer_list overloads may be unnecessary, and turn what should be a compile-time arity check to a runtime assertion on size(). They could help to support very high dimensionality, higher than the maximum supported number of function arguments, but I don't think most relevant platforms actually have such a limitation, and low dimensionality could be penalized by adding the overhead of the pointers and "hard" stack allocation.The indexing operator (operator []) takes exactly one operand. To work around that, I made the variadic operator() member templates. I even made them return a sub-array when fewer arguments than dimensions were given. I made versions of at to match. Then I read the Standard and found out operator [] now supports multiple arguments indirectly through the braced-init-list syntax.
Compilers should make true array access faster than pointer arithmetic.
Stack allocation is the point of things like std::array over the regular containers. Plus, non-dynamic containers can be used in constant expressions, including constexpr contexts.
Another approach would be to make std::multi_array an alias template to a nested std::array type. The multidimensional accessor overloads could be added to one-dimensional std::array and delegate recursively to the underlying type. This would support existing code which nests std::array, or even other numeric libraries inside std::array (which I have done with Eigen; there are advantages to this and practical use cases). It would incur nonsense semantics for operator() on an array over a type with well-defined operator() ( std::size_t [, std::size_t … ] )— but that's a corner case, and array::operator() isn't so far defined anyway. The interface and implementation would be more lightweight.This multi_array would be like the stack and queue adaptors?
template< typename t, std::size_t next_extent, std::size_t ... rem_extent >
struct multi_array_helper // metafunction
{ typedef std::array< typename multi_array_helper< t, rem_extent ... >::type > type; };
template< typename t, std::size_t extent >
struct multi_array_helper< t, extent >
{ typedef std::array< t, extent > type; };
template< typename t, std::size_t ... extent >
using multi_array = typename multi_array_helper< t, extent ... >::type; // alias template
You can already make an array of a built-in array type, another std::array, or a custom array-like class type. But the point was to make something more integrated.
When was the last time n-adic operator[] support was considered? Doesn't the potential use in the scientific arena outweigh the need to support abuse of the comma operator inside square brackets? C'mon, let's deprecate that syntactic sucker.I don't know why non-single parameters are banned for operator[]. But now C++11 has given us a single std::initializer_list parameter as a workaround.
On Sunday, September 8, 2013 12:30:46 AM UTC+8, Daryle Walker wrote:
On Friday, September 6, 2013 9:58:30 PM UTC-4, David Krauss wrote:I think the initializer_list overloads may be unnecessary, and turn what should be a compile-time arity check to a runtime assertion on size(). They could help to support very high dimensionality, higher than the maximum supported number of function arguments, but I don't think most relevant platforms actually have such a limitation, and low dimensionality could be penalized by adding the overhead of the pointers and "hard" stack allocation.The indexing operator (operator []) takes exactly one operand. To work around that, I made the variadic operator() member templates. I even made them return a sub-array when fewer arguments than dimensions were given. I made versions of at to match. Then I read the Standard and found out operator [] now supports multiple arguments indirectly through the braced-init-list syntax.
What other class braced-init-lists which are required to be an exact size? Just because the core language makes something possible, doesn't make it a good idea.
Compilers should make true array access faster than pointer arithmetic.
???
Another approach would be to make std::multi_array an alias template to a nested std::array type. The multidimensional accessor overloads could be added to one-dimensional std::array and delegate recursively to the underlying type. This would support existing code which nests std::array, or even other numeric libraries inside std::array (which I have done with Eigen; there are advantages to this and practical use cases). It would incur nonsense semantics for operator() on an array over a type with well-defined operator() ( std::size_t [, std::size_t … ] )— but that's a corner case, and array::operator() isn't so far defined anyway. The interface and implementation would be more lightweight.This multi_array would be like the stack and queue adaptors?
No, an alias template — a metafunction which looks like a class template.
template< typename t, std::size_t next_extent, std::size_t ... rem_extent >
struct multi_array_helper // metafunction
{ typedef std::array< typename multi_array_helper< t, rem_extent ... >::type > type; };
template< typename t, std::size_t extent >
struct multi_array_helper< t, extent >
{ typedef std::array< t, extent > type; };template< typename t, std::size_t ... extent >
using multi_array = typename multi_array_helper< t, extent ... >::type; // alias templateYou can already make an array of a built-in array type, another std::array, or a custom array-like class type. But the point was to make something more integrated.
"Separate" is the opposite of "integrated." The best-integrated solution is the one which leverages existing facilities and avoids creating new types.
As I said, my proposal would support existing code using nested std::array< std::array< … > > and other non-standard array types inside std::array.
None, as far as I know. But the other braced-init-lists in the standard are either aggregate initialization or constructor calls (especially std::initializer_list, especially for the dynamic containers). This would be the first Standard type to use the operator []( std::initializer_list ) feature.
operator [] ( std::array< std::size_t, sizeof ... (extents) > )
A class with an indexing operator with an initializer-list parameter that's flexible as you suggest could be something like std::vector,
Given b[j] and c[j], where j is an integer value, b is an array, and c is a pointer, the assembly instructions between the two differ and the array access should be faster than the pointer version.
I don't prefer nested smart-array approach. It looks ugly,
and if there's trailing padding in any instance, any higher-level instances will get padding holes everywhere.
As an exercise in using variadic templates, I chose a multi-dimensional variant of std::array. I eventually made the interface match std::array when the number of extents given is one. When wondering if I should put the class template up for consideration, I realized that it would be so close to std::array, that I shouldn't propose my class directly for the Standard Library, but propose a change to std::array instead.I just put it up at https://github.com/CTMacUser/multiarray-iso-proposal, for requesting comments before officially proposing it. (I should switch to HTML or some other rich-text system for the next draft....)
On Friday, September 6, 2013 8:17:12 PM UTC-4, Daryle Walker wrote:As an exercise in using variadic templates, I chose a multi-dimensional variant of std::array. I eventually made the interface match std::array when the number of extents given is one. When wondering if I should put the class template up for consideration, I realized that it would be so close to std::array, that I shouldn't propose my class directly for the Standard Library, but propose a change to std::array instead.I just put it up at https://github.com/CTMacUser/multiarray-iso-proposal,
On Thursday, September 12, 2013 5:54:24 AM UTC+8, Daryle Walker wrote:On Friday, September 6, 2013 8:17:12 PM UTC-4, Daryle Walker wrote:As an exercise in using variadic templates, I chose a multi-dimensional variant of std::array. I eventually made the interface match std::array when the number of extents given is one. When wondering if I should put the class template up for consideration, I realized that it would be so close to std::array, that I shouldn't propose my class directly for the Standard Library, but propose a change to std::array instead.I just put it up at https://github.com/CTMacUser/multiarray-iso-proposal,
Please avoid putting the comma after a non-linked URL on this board, and please provide a link to the actual file. The best I can find is this link which provides incorrect MIME so the browser doesn't render anything, but displays HTML source.
How much testing and research has gone into this? (Has it actually been used by people in a real project? How much have you used it?) Boost.Multiarray isn't even mentioned. Is submission as an international standard really the next step for this library?
I can't really read it, but only looking at make_array,
- The common_type makes it too easy to accidentally get the wrong type of array. Besides numeric cases, a base-class argument would incur slicing derived-class arguments.
- Separate T parameter does not seem to serve a purpose, except perhaps to prevent a signature that would instantiate ill-defined std::common_type<>, but that doesn't seem a likely reason. The solution to that problem would be a requires clause.
- This does not conceptually belong to a "multiarray" library. It is a utility for creating a one-dimensional array. (Although it does evaluate the array_t metafunction, it is a pointless exercise as the arguments seem to map directly to std::array<T,N>. Although I can't see where std::array<…>::type is defined at all. Using a valid object type as a metafunction is sure to be controversial, if that's really what this is doing, but I'll wait until I can read the proposal without straining.)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On Thursday, September 12, 2013 5:54:24 AM UTC+8, Daryle Walker wrote:On Friday, September 6, 2013 8:17:12 PM UTC-4, Daryle Walker wrote:As an exercise in using variadic templates, I chose a multi-dimensional variant of std::array. I eventually made the interface match std::array when the number of extents given is one. When wondering if I should put the class template up for consideration, I realized that it would be so close to std::array, that I shouldn't propose my class directly for the Standard Library, but propose a change to std::array instead.I just put it up at https://github.com/CTMacUser/multiarray-iso-proposal,
Please avoid putting the comma after a non-linked URL on this board, and please provide a link to the actual file. The best I can find is this link which provides incorrect MIME so the browser doesn't render anything, but displays HTML source.
How much testing and research has gone into this? (Has it actually been used by people in a real project? How much have you used it?) Boost.Multiarray isn't even mentioned. Is submission as an international standard really the next step for this library?
I can't really read it, but only looking at make_array,
- The common_type makes it too easy to accidentally get the wrong type of array. Besides numeric cases, a base-class argument would incur slicing derived-class arguments.
- Separate T parameter does not seem to serve a purpose, except perhaps to prevent a signature that would instantiate ill-defined std::common_type<>, but that doesn't seem a likely reason. The solution to that problem would be a requires clause.
- This does not conceptually belong to a "multiarray" library. It is a utility for creating a one-dimensional array. (Although it does evaluate the array_t metafunction, it is a pointless exercise as the arguments seem to map directly to std::array<T,N>. Although I can't see where std::array<…>::type is defined at all. Using a valid object type as a metafunction is sure to be controversial, if that's really what this is doing, but I'll wait until I can read the proposal without straining.)
On Wednesday, September 11, 2013 8:05:08 PM UTC-4, David Krauss wrote:How much testing and research has gone into this? (Has it actually been used by people in a real project? How much have you used it?) Boost.Multiarray isn't even mentioned. Is submission as an international standard really the next step for this library?As I said earlier, I came up with this idea a few months ago as an exercise. AFAIK, it's only been used in my unit test program for it. But I don't think there's any experience requirement; as long as a proposal is submitted, a library with a decade of in-field hard testing and a library from a five-minute as^H^Hhead-pull are equivalent. Since this library isn't trying to bring new innovations in (C++) programming, simple inspection is still useful.
I haven't mentioned Boost.Multiarray since it's dynamic-memory based.
That means each instantiation carries around a type-alias to whatever built-in array type it uses for its data. My sample library uses "array_type" as the name. A trait for getting a built-in array type given an element type an a list of extents should be a separate class template, but the best name is already being used! Since I need that type-alias around anyway, why not pull double-duty and use "type" in the Standard version?
On Friday, September 13, 2013 1:16:04 AM UTC+8, Daryle Walker wrote:On Wednesday, September 11, 2013 8:05:08 PM UTC-4, David Krauss wrote:How much testing and research has gone into this? (Has it actually been used by people in a real project? How much have you used it?) Boost.Multiarray isn't even mentioned. Is submission as an international standard really the next step for this library?As I said earlier, I came up with this idea a few months ago as an exercise. AFAIK, it's only been used in my unit test program for it. But I don't think there's any experience requirement; as long as a proposal is submitted, a library with a decade of in-field hard testing and a library from a five-minute as^H^Hhead-pull are equivalent. Since this library isn't trying to bring new innovations in (C++) programming, simple inspection is still useful.
Except that it is trying to be innovative.
Simple (code) inspection is useful, but at this stage you or your friends should be the one doing it. IMHO (I'm relatively new here) the official channels have their hands full without reviewing almost completely untested, rough drafts. There's no rule against submitting whatever you like, but that doesn't mean you should.
There are more issues, for example arr[ arr.size() - 1 ] is all but guaranteed to go past the end in the multidimensional case. value_type and dereference need to be sorted out. Cursory usage will turn up major flaws the library.
I haven't mentioned Boost.Multiarray since it's dynamic-memory based.
Memory allocation is but one concern.
That means each instantiation carries around a type-alias to whatever built-in array type it uses for its data. My sample library uses "array_type" as the name. A trait for getting a built-in array type given an element type an a list of extents should be a separate class template, but the best name is already being used! Since I need that type-alias around anyway, why not pull double-duty and use "type" in the Standard version?
Using an object type as a metafunction requires that all declarations besides ::type be instantiated when the metafunction is evaluated. This requires that those declarations will be well-formed even though they aren't used, and it requires the compiler to do the extra work.
B'sides… separation of concerns. Need I say more?
P.S. Sorry.
It's of course not quite complete yet: I need to go over the description of std::array with a fine toothed comb to ensure that my constexpr/noexcept specifications are correct.
Calling the subscript operator like that is a misuse. Doing it is just like indexing by T in a multidimensional built-in array of T using one index.
A sequence container is linear, but a multi-dimensional container is non-linear.
Fortunately, those definitions only come in conflict with the definitions of operator[]() and at(). I specifically exclude those two operations from the sequence requirements with non-one rank in my modifications to section 23.2.3 and refer to section 23.3.2.D for the substitute operations.
Boost.Multiarray uses a different static interface (The template arguments are the element type and the rank), so it's incompatible with my proposal to begin with, which extents the current std::array in a backwards-compatible way. BM gets the actual extent values during the constructor call, while new std::array keeps them in the template header.
Both classes support indexing through bracket chains and a single multi-index object. BM has an extensive view system,
while new std::array keeps the lack of same as current std::array and built-in arrays do. BM has a same-type & same-rank reshaping, one preserving total size and another for adding or removing elements; I just added a reshaping function that can change type, rank, and total size, but it always makes a copy.
I tried to check this, but Chapter 14 (Template) is very deep and dense.
On Tuesday, September 17, 2013 3:53:27 PM UTC+8, Daryle Walker wrote:Calling the subscript operator like that is a misuse. Doing it is just like indexing by T in a multidimensional built-in array of T using one index.
According to you. Without the special exception you propose for table 101, generic code can assume that & c[n] == &* ( c.begin() + n ).
A sequence container is linear, but a multi-dimensional container is non-linear.
A multi-dimensional array is always linear. Each immediate subobject is an array.
Fortunately, those definitions only come in conflict with the definitions of operator[]() and at(). I specifically exclude those two operations from the sequence requirements with non-one rank in my modifications to section 23.2.3 and refer to section 23.3.2.D for the substitute operations.
This is inconsistent with other containers.
Boost.Multiarray uses a different static interface (The template arguments are the element type and the rank), so it's incompatible with my proposal to begin with, which extents the current std::array in a backwards-compatible way. BM gets the actual extent values during the constructor call, while new std::array keeps them in the template header.
There are far more applications for variable-size multidimensional arrays.
Both classes support indexing through bracket chains and a single multi-index object. BM has an extensive view system,
Whether you have a fixed or variable amount of data, the multiply indexed views have the same use. For example some code could work with both a fixed-size kernel and the data series it operates on.
Perhaps a generic view is what we need, along the lines of std::slice and std::gslice but divorced from valarray. Those classes could even perhaps be reused.
while new std::array keeps the lack of same as current std::array and built-in arrays do. BM has a same-type & same-rank reshaping, one preserving total size and another for adding or removing elements; I just added a reshaping function that can change type, rank, and total size, but it always makes a copy.
This is a symptom of having used the multidimensional object to specify the underlying storage. The view and the storage are separate concerns.