220 14544 <e54ad82a-312b-4bbd-a64a-a7f612bd2e15@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: phdofthehouse@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Comments on n3976 (array_view)
Date: Fri, 14 Nov 2014 13:17:17 -0800 (PST)
Lines: 1139
Approved: news@gmane.org
Message-ID: <e54ad82a-312b-4bbd-a64a-a7f612bd2e15@isocpp.org>
References: <ef9f1714-0b21-4ff5-87f3-ba3f4c8d06f4@isocpp.org>
 <CANh-dXnY3oNR6g2Jw7r+sT=dXn268OQ+TZ8uFcYzYcPBSWfGUw@mail.gmail.com>
 <81f95afc-7a67-45cd-950c-433528b2b8db@isocpp.org>
 <e5fe7212-7f50-4293-8251-9e49102a32ce@isocpp.org>
 <CAKJfoCE5FnF+8YCqfXvG+5zUWs5paZGmViujbwt4_rs2pdWD2Q@mail.gmail.com>
 <93261ea6-195a-4838-8283-397a538e9444@isocpp.org>
 <e4583a57-3eff-43d1-8086-9ca525fcfbdf@isocpp.org>
 <CAKJfoCHLU7=_JAhWam6nazgs8sm9efrSjseSmhfAeXoSGvqb1g@mail.gmail.com>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; 
	boundary="----=_Part_716_988142105.1415999837544"
X-Trace: ger.gmane.org 1415999847 468 80.91.229.3 (14 Nov 2014 21:17:27 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Fri, 14 Nov 2014 21:17:27 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDN2PNGWZQEBBXXCTGRQKGQEVNF3CCY@isocpp.org Fri Nov 14 22:17:21 2014
Return-path: <std-proposals+bncBDN2PNGWZQEBBXXCTGRQKGQEVNF3CCY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-pa0-f72.google.com ([209.85.220.72])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBDN2PNGWZQEBBXXCTGRQKGQEVNF3CCY@isocpp.org>)
	id 1XpOF6-0006po-03
	for gclcip-std-proposals@m.gmane.org; Fri, 14 Nov 2014 22:17:20 +0100
Original-Received: by mail-pa0-f72.google.com with SMTP id kx10sf104377133pab.7
        for <gclcip-std-proposals@m.gmane.org>; Fri, 14 Nov 2014 13:17:19 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe
         :content-type;
        bh=MhgwfZMLW/ZLKcsRsl8OmjQjZzObvv1rYihurJV3mQU=;
        b=uvjStYoXqfea4scKh05GhPDQxw42Q92ohiYEyMN69Ia8Kg/+zMe5udJdS7vCZpwr8m
         bqI1F7ZzlGp9IbkDKYinFw/Ee8bEXhnp39Eg025w3xbdaxPO33yOtEKHrRR1gbnd95fW
         wcI2M13iQ/gKnOfJARSB8z7B22TUSjE2X6tuJdEJ+QHWjiDmuOgIf5KJHKeUMBRPYi0Y
         zF5/CTyUpFXsfoBgaghi3BPwuuNUn/pzbdK4ztFcSqzuL5bIiGkjIo2+19DTzF/tgH9/
         ok2iw/NzFBu4QpxiSX+XOxDqgy4h6MGOVdhS8KBJcxA3Kmrv3w2kcpYnRCC+UIc6odjm
         GPaQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe:content-type;
        bh=MhgwfZMLW/ZLKcsRsl8OmjQjZzObvv1rYihurJV3mQU=;
        b=WrzBSqa88vZbjricE/DWXKpJLOo11mUtC9hXxaq4zIe+jrU3vGwnWniPnrIK5JoTaO
         FeZ4y0uwT4sY7MdvkZSP6jlbXaJ/9SO1n7G4fwJecnzKWIFLUqdpDW+7UipI7MPK9rGm
         +sWwqR6bj7FmbQvD+/Jm7lgzLB5L54XW0YSjj3SpwMph485wvtLhvbKZwlWTNjFnFgHm
         D1x0Ve37ZuWHXEkyFi47157enrrkb/p+Q3v3Dzqf43PHWkdrk+dWUvPHEh19cVFdL8rE
         mRtiKnVMgfXNzkwpq8r1HcJomF1xw5pzAo3qSmH04V1QbG524VYoCZF9L5EDFVq4Z3Rv
         ZhBQ==
X-Gm-Message-State: ALoCoQmokKCOK4Idlrn7zWtcfaMhEW8zXyanCARteOeOrV1itwtd/pI5cCULAoOp1bYTBlLEtTRJ
X-Received: by 10.66.222.166 with SMTP id qn6mr49753779pac.6.1415999838969;
        Fri, 14 Nov 2014 13:17:18 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.140.39.52 with SMTP id u49ls4075566qgu.71.gmail; Fri, 14 Nov
 2014 13:17:18 -0800 (PST)
X-Received: by 10.140.97.34 with SMTP id l31mr1469qge.42.1415999838161;
        Fri, 14 Nov 2014 13:17:18 -0800 (PST)
In-Reply-To: <CAKJfoCHLU7=_JAhWam6nazgs8sm9efrSjseSmhfAeXoSGvqb1g@mail.gmail.com>
X-Original-Sender: phdofthehouse@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:14544
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/14544>

------=_Part_716_988142105.1415999837544
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

I think that's convoluting the idea I'm trying to present here; the casting=
=20
point your making... seems to be orthognal to what I'm trying to say (not=
=20
to mention... dangerous/broken to implement? Changing the way a *std::array=
*=20
dereferences would break code everywhere, especially code that takes a=20
pointer to an array of std::array's (e.g., a vector of specifically-sized=
=20
*std::array*s) that suddenly behaved as if it was calling operator[] inside=
=20
of the pointed-to T? That's not a very good idea, I don't think).

That aside, the use case here is being able to nail down as many pieces of=
=20
computation to the compiler as possible: array_view<T, ...> and=20
strided_array_view<T, ...> are analogous to a c-style or std::array-style=
=20
declarations, with the benefit of providing the dimensions at compile-time.=
=20
This allows a constexpr operator[] to throw out all of the multiplication=
=20
and index caluclations to get to exact target index exactly before the=20
program runs and instead becomes direct access to the memory of interest;=
=20
this becomes a particularly interesting case for me as any special=20
optimizations like SIMD can be seen ahead of time by the compiler and=20
substituted in, since it can view those indices ahead of time and know the=
=20
offsets.

However, I'm not sure if that's already possible with just a=20
constexpr-enabled array_view that takes its dimensions, strides and bounds=
=20
at runtime. I have already written a buffer_view<T, dimension> in my own=20
code based on the proposal paper presented, and then also wrote an=20
array_view and strided_array_view with compile-time strides and bounds. My=
=20
current compiler (VC++) chokes on constexpr, so I mostly wanted to ask=20
about it here, if anyone else had a similar idea.

On Friday, November 14, 2014 3:51:54 PM UTC-5, Jeremy Maitin-Shepard wrote:
>
> If the size is known at compile time, an actual reference to std::array=
=20
> (or a multi-dimensional static-sized array counterpart) would be much=20
> better, as this eliminates the need for an extra type, and makes referenc=
e=20
> decay do the right thing.  If the current language rules do not permit th=
e=20
> casting of an arbitrary pointer T *x where [x, x+size) is a valid range, =
to=20
> be a pointer to std::array<T,size>*, then I think the language rules shou=
ld=20
> be changed, as this is clearly extremely useful and any loss of=20
> optimization possibilities are probably minimal.
>
> On Fri, Nov 14, 2014 at 12:29 PM, <phdoft...@gmail.com <javascript:>>=20
> wrote:
>
>> As a small addition, has anyone considered perhaps calling the class=20
>> buffer_view<typename T, size_type dimensions>
>>
>> and then leaving the name *array_view* for a compile-time version of=20
>> this class (to match std::array)?
>>
>> I don't know if a fully constexpr-qualified version of the buffer_view=
=20
>> class will have the same benefit as a compile-time defined=20
>> array_view<typename T, size_type... dimension_sizes>
>>
>> class (with *strided* variants for buffer_view and array_view).
>>
>>
>> On Friday, June 27, 2014 1:00:54 AM UTC-4, =C5=81ukasz Mendakiewicz wrot=
e:
>>>
>>> I do understand your rationale in many of the points you are raising,=
=20
>>> and I am aware of other existing libraries, which in some cases made=20
>>> different design decisions. However many of the choices are mutually=20
>>> exclusive and in my opinion it is impossible to converge on the "single=
=20
>>> best design". Many of the design decisions in our proposal are also=20
>>> compromises.
>>>
>>> I disagree with your judgment that we should strive to find an ultimate=
=20
>>> solution before moving forward with any proposal. Lack of array_view or=
 a=20
>>> similar type is clearly a gap in C++ Standard, which many libraries are=
=20
>>> addressing in different ways. We took the first stab in trying to addre=
ss=20
>>> this deficiency with putting forward the type we are familiar with, hav=
e=20
>>> worked with successfully for over 2 years, and in the process we were a=
lso=20
>>> fixing all issues we were aware of. It surely is not rock solid -- noth=
ing=20
>>> is -- and many use-cases might have benefit from tailoring details=20
>>> differently to cater each of them, but we have to start somewhere.
>>> Importantly, we are not "standardizing" array_view yet. If it passes LW=
G=20
>>> voting on the next Committee meeting it will be merely appended to one =
of=20
>>> TSs (unless anything changes, this should be Library Fundamentals TS) a=
nd=20
>>> on track to be considered for C++17. The three years lead time is inten=
ded=20
>>> exactly to gather the wider practical experience you are concerned abou=
t.
>>>
>>> I hope this helps to clarify our position.
>>>
>>> On Monday, June 16, 2014 5:49:39 PM UTC-7, Jeremy Maitin-Shepard wrote:
>>>
>>>> On Sun, Jun 15, 2014 at 9:38 PM, =C5=81ukasz Mendakiewicz <
>>>> l.menda...@live.com> wrote:
>>>>
>>>>> Thank you Jeffrey for adding me on the thread and for your initial=20
>>>>> response -- which I almost universally agree with.
>>>>>
>>>>> Jeremy, thank you for your detailed feedback. First, I believe that=
=20
>>>>> most of the disagreement stems from the approach to the proposal. You=
've=20
>>>>> commented that "it doesn't make sense to standardize a partial soluti=
on;=20
>>>>> better to work out a good, complete interface outside the standard". =
This=20
>>>>> is opposite to the "crawl, walk, run" philosophy we have taken when w=
riting=20
>>>>> this document up. We recognize that we have only explored some parts =
of the=20
>>>>> design space, because as you have rightly observed our experience is=
=20
>>>>> limited to C++ AMP, which constitutes only a specific data parallel=
=20
>>>>> approach to algorithms. Of course we believe that this is a solid=20
>>>>> foundation that can be generalized and built upon, hence the proposal=
.. But=20
>>>>> we deliberately avoided any design decisions which may be controversi=
al or=20
>>>>> result in a prolonged tug of war, instead intending for subsequent=20
>>>>> proposals (not necessarily authored by us) to fill the gaps. Certainl=
y,=20
>>>>> should anything being proposed now be a possible hindrance for any=20
>>>>> reasonable extension, it must be addressed sooner than later, however=
 I=20
>>>>> think that none of the lacks pointed by you belong to this category.
>>>>>
>>>> I think it is basically impossible to nail down even a "minimal"=20
>>>> interface without considering the design of a complete library.  If yo=
u=20
>>>> looked at 10 different, widely-used C++ multidimensional array librari=
es=20
>>>> and saw that all of their interfaces shared a given attribute, then=20
>>>> standardizing that attribute of the interface would likely be a safe=
=20
>>>> choice.  Obviously that is not the case here, though.
>>>>
>>>> Some examples of design options:
>>>> - Make array_view parameterized by the pointer type, rather than the=
=20
>>>> value type.  This allows it to hold smart pointers of various types, o=
r a=20
>>>> pointer that represents GPU memory, or a smart pointer that represents=
 GPU=20
>>>> memory, etc.  If the pointer is to GPU memory, reading and writing won=
't=20
>>>> work (and won't be allowed at compile-time), but the indexing, slicing=
,=20
>>>> sectioning and other operations on the array_view representation itsel=
f can=20
>>>> still be used.  This is the decision I took in my own in-house library=
.. =20
>>>> Allowing array_view to hold a smart pointer means you don't need a sep=
arate=20
>>>> type to represent an array_view with ownership.  (Sectioning and slici=
ng=20
>>>> produces a result with the pointer decayed to a regular pointer.)  You=
 can=20
>>>> also use a __restrict__ pointer for an array_view type used as a funct=
ion=20
>>>> parameter to indicate lack of aliasing.
>>>>
>>>> - Make bounds and index just generic fixed-size vector types.  In this=
=20
>>>> case iterators on bounds should iterate over the components, rather th=
an=20
>>>> iterate over coordinates within the bounds.
>>>> =20
>>>> - More generally, the proposal distinguishes between array_view and=20
>>>> strided_array_view, but doesn't allow for more fine-grained informatio=
n to=20
>>>> be provided at compile time, such as the number of trailing contiguous=
=20
>>>> dimensions, alignment information, etc.
>>>>
>>>>> >>> Some particular issues with the proposed design include:=20
>>>>> >>>=20
>>>>> >>> - No iterators are provided for array_view or strided_array_view,=
=20
>>>>> a clear=20
>>>>> >>> omission in the interface.  For a multidimensional array, there=
=20
>>>>> are two=20
>>>>> >>> obvious types of iteration that may be desired:=20
>>>>> >>>   1. iterating over just the first dimension;=20
>>>>> >>>   2. iterating over a flat view of all of the elements.  For a=20
>>>>> strided=20
>>>>> >>> array, iterating over a flat view cannot be done efficiently=20
>>>>> without=20
>>>>> >>> segmented/hierarchical iterators.=20
>>>>> >>>   Which of these should be the default (i.e. provided through=20
>>>>> begin() and=20
>>>>> >>> end() rather than through some adaptor) is not clear,=20
>>>>> >>
>>>>> >> From the Zen of Python, "In the face of ambiguity, refuse the=20
>>>>> >> temptation to guess."=20
>>>>> >
>>>>> > That's true, but no adaptors to provide the functionality=20
>>>>> unambiguously are provided either.  For the particular case of a=20
>>>>> one-dimensional array, there is no ambiguity, and not being able to e=
asily=20
>>>>> use array_view with standard algorithms or range-based for is a serio=
us=20
>>>>> usability issue.  This will only become worse if/when standard algori=
thm=20
>>>>> overloads that take ranges rather than iterator pairs are added.
>>>>>
>>>>> To the list of possible alternatives, I would add an option that was=
=20
>>>>> proposed somewhere in the prior discussion on the proposal --=20
>>>>> "hierarchical" array_view/elemental iterator, i.e. an iterator that f=
or=20
>>>>> array_view<T, Rank> with Rank > 1 iterates over array_view<T, Rank-1>=
; and=20
>>>>> over T for Rank =3D=3D 1.
>>>>>
>>>> Yes, that is a better way of expressing what I meant by "iterating ove=
r=20
>>>> just the first dimension".  I believe this makes the most sense, but t=
hen=20
>>>> it becomes desirable to have size() be the size of the first dimension=
 for=20
>>>> consistency with the iterators, and instead add a num_elements() that=
=20
>>>> returns the total number of elements.  The correct definition of size(=
) is=20
>>>> hard to decide without figuring out how iterators should work.
>>>>
>>>> The other issue is that if the iterators are hierarchical, you need a=
=20
>>>> new hierarchical for_each that effectively expands to N nested for loo=
ps=20
>>>> for N-dimensional arrays and which can operate on multiple arrays (of =
the=20
>>>> same size).  This way you can express element-wise operations without =
any=20
>>>> overhead.
>>>>
>>>>> It is however worth pointing out that in the first round of review=20
>>>>> with LEWG at Issaquah meeting, the vocal unchallenged feedback for=20
>>>>> iterators was "I do not want iterators for the views", thus we did no=
t put=20
>>>>> much effort into contemplating adding any. Even though the choice for=
 Rank=20
>>>>> =3D=3D 1 is "obvious", we consider this a corner case for array_view,=
 and would=20
>>>>> rather have a holistic approach.
>>>>> There remains the possibility to add some form of the iterator as a=
=20
>>>>> future extension.
>>>>>
>>>> Well, you can take my comments as a challenge to that view.  Rank =3D=
=3D 1=20
>>>> may be a "corner" case, but is likely to be used more frequently than =
all=20
>>>> other cases combined.  A 1-dimensional array view that can't be used w=
ith=20
>>>> for-range loops, boost (or std?) range adapters, etc. is a non-starter=
..
>>>>
>>>>> >>> - No data() access member for strided_array_view.  This is=20
>>>>> presumably=20
>>>>> >>> omitted because the memory is non-contiguous, but given that=20
>>>>> >>> strided_array_view is a thin wrapper, there has to be a convenien=
t=20
>>>>> way to=20
>>>>> >>> get at the underlying memory.=20
>>>>> >>
>>>>> >> Why "has to"?=20
>>>>> >
>>>>> > Because the user might want to convert the array to another=20
>>>>> representation for use by another piece of code/library, e.g. FFTW or=
=20
>>>>> Eigen, CUDA memcpy, etc.  Under the proposed interface, for a 3-dimen=
sional=20
>>>>> stided array view, you have to use &arr[0][0][0].  This is even worse=
 than=20
>>>>> having to do &vec[0] for std::vector, since the same expression canno=
t be=20
>>>>> used independent of the dimensionality.
>>>>>
>>>>> data() on strided_array_view could be harmful, as there is no=20
>>>>> guarantee of contiguity, which a developer / function template might=
=20
>>>>> assume. Please note that for every other case in the Standard, the ra=
nge=20
>>>>> [data(), data()+size()) is valid/safe, thus providing other semantics=
 here=20
>>>>> would be dubious.
>>>>> Granted, one can perform &arr[0][0][0] and run afoul, but that is no=
=20
>>>>> different than e.g. &my_list.front().
>>>>> It could be possible to provide "unsafe_data()" interface, which woul=
d=20
>>>>> have to be consumed along with stride(), however I do not see much be=
nefit=20
>>>>> here over just using the "proper" interface -- bounds() and operator[=
]().
>>>>>
>>>> Calling it noncontiguous_data() is fine, though certainly then=20
>>>> array_view should have an noncontiguous_data() (in addition to data())=
 as=20
>>>> well for consistency.  I don't think unsafe_data is really the right n=
ame,=20
>>>> though the functionality is more important than the name.  &arr[0][0][=
0]=20
>>>> has the disadvantage that it is more verbose and doesn't allow for wri=
ting=20
>>>> generic code that works with any number of dimensions.  Just using the=
=20
>>>> "proper" interface isn't a solution.  A fundamental component like=20
>>>> multidimensional arrays cannot be a "walled garden".  The (pointer, bo=
unds,=20
>>>> strides) representation, which numerous other libraries like FFTW use =
as=20
>>>> well, should be transparent.
>>>>
>>>>> >>> - Slicing is limited: it is not possible to take a slice in a=20
>>>>> dimension=20
>>>>> >>> other than the first.=20
>>>>> >>
>>>>> >> I think that's called "section()".=20
>>>>> >
>>>>> > Well, that takes a "section" but does not reduce the dimensionality=
=20
>>>>> like "slice". [...] Certainly there is a large design space for gener=
al=20
>>>>> subscripting and it almost certainly requires a fair amount of templa=
te=20
>>>>> metaprogramming, but this is very useful functionality
>>>>>
>>>>> Yes, slicing and sectioning are slightly different. It is however=20
>>>>> important to note that slicing in its current form always guarantees =
the=20
>>>>> contiguity of the result, thus the return type may be array_view. The=
 more=20
>>>>> general cases (as you are describing) would result in a potentially s=
trided=20
>>>>> resulting view, which would need to be typed strided_array_view. This=
 is=20
>>>>> why it is important IMO to distinguish these two cases.
>>>>> In the current form of the proposal we decided to provide the minimal=
=20
>>>>> design -- only the first version, which in our opinion might be handy=
 for=20
>>>>> users used to C-style multidimensional addressing (i.e. arr[3][1][4] =
v=20
>>>>> arr[{3, 1, 4}]), which actually you used above :).
>>>>> The latter generic case can be trivially added as an extension to the=
=20
>>>>> interface. I agree it may be useful, and if the current design is acc=
epted=20
>>>>> for the TS, I encourage you to propose such extension (or nag us for =
follow=20
>>>>> ups :)).
>>>>>
>>>>> >>> - It is not clear whether it is really useful to have bounds and=
=20
>>>>> index be=20
>>>>> >>> separate types (though should probably at least be explicitly=20
>>>>> convertible to=20
>>>>> >>> each other).=20
>>>>> >>
>>>>> >> It adds a bit of type safety. Adding two bounds, for instance,=20
>>>>> doesn't=20
>>>>> >> make a lot of sense.=20
>>>>> >
>>>>> > I agree that type safety is in principle useful, but it is=20
>>>>> impossible to predict what relationships might hold in any given prog=
ram,=20
>>>>> and so there is the question of whether the safety it adds is worth t=
he=20
>>>>> cost of having to explicitly work around it in the cases that it is t=
oo=20
>>>>> restrictive.  Certainly if they are separate types there needs to be =
a way=20
>>>>> to (explicitly) convert.
>>>>>
>>>>> I agree with both of you :).
>>>>> These are separate types, because their meaning and semantics are=20
>>>>> different. It was also discussed in N3851, Appendix, II. The mental m=
odel I=20
>>>>> use for reasoning about them is: index ~ vector and bounds ~ point (m=
ore=20
>>>>> specifically: a zero-bound, axis-aligned rectangle described by its m=
aximum=20
>>>>> point), which makes the set of available operators apparent.
>>>>> I understand the explicit conversions between these two types, even=
=20
>>>>> though not theoretically sound, might be handy in practice and should=
 be=20
>>>>> added.
>>>>>
>>>> If we follow that logic, a point is a vector from the origin. =20
>>>> Therefore index should just be Vector<ptrdiff_t,N> and bounds<N> could=
 have=20
>>>> a Vector<ptrdiff_t,N> member.  However, it seems like it would be simp=
ler=20
>>>> to just have bounds be Vector<ptrdiff_t,N> as well and save the troubl=
e of=20
>>>> the explicit conversions.  What type of error does the bounds/index=20
>>>> distinction prevent?  More generally, I am not sure why we shouldn't t=
hink=20
>>>> of an index as a point as well.  If we want the last element in an arr=
ay x,=20
>>>> we have : x.bounds() - 1  (or x.bounds() - {1,1, ...}).  We want to us=
e=20
>>>> this as an index, but the current operator definitions would have it b=
e a=20
>>>> bounds.
>>>>
>>>>> > As a specific example, consider if we want to compute the bounds of=
=20
>>>>> a valid convolution if we have an array x and a filter k.  The bounds=
 of=20
>>>>> the result are: x.bounds - k.bounds + 1.  None of the arithmetic oper=
ators=20
>>>>> defined in the proposal help me with that; I'd just have to write a l=
oop. =20
>>>>> Even if the arithmetic operators weren't limited by the bounds/index=
=20
>>>>> distinction, there would still be no way to create a constant-valued=
=20
>>>>> vector, i.e. to handle the constant 1.
>>>>>
>>>>> Explicit conversions would help with the first part, right? I hope yo=
u=20
>>>>> are also not suggesting any such conversion should be implicit?
>>>>> However I do not really understand what do you mean in the second=20
>>>>> part, "a constant-valued vector". We purposefully allow to create bot=
h=20
>>>>> bounds<1> and index<1> from a scalar; and disallow such operation for=
 Rank=20
>>>>> > 1 (mostly because the semantics are not obvious, e.g. for rank 2, s=
hould=20
>>>>> index<2>{16} be {0, 16}, {16, 0} or {16, 16}).
>>>>> So net-net, in your example you should be able to do: x.bounds -=20
>>>>> index<2>{k.bounds} + {1, 1}. It a little more long-winded, but IMO ea=
sier=20
>>>>> to comprehend than the original.
>>>>>
>>>> I don't think the explicit conversion to index adds to the clarity. =
=20
>>>> Also, the problem with {1, 1} is that it depends on the dimensionality=
.. =20
>>>> The interface should be designed to be convenient for generic code.  I=
=20
>>>> would suggest a Scalar<T> type generated by a wrapper function scalar,=
 from=20
>>>> which bounds and index can be implicitly constructed and which can be =
used=20
>>>> in all of the operators.
>>>>
>>>>> > Another related issue I didn't notice before: the only way to=20
>>>>> construct an index or bounds type is from an initializer_list.  There=
 is no=20
>>>>> (explicit) conversion from std::array, for instance.  It is quite lik=
ely=20
>>>>> that an index or bounds value would be computed by some other code, t=
hat=20
>>>>> may use a different representation.
>>>>>
>>>>> Yes, we should add (const value_type* begin, const value_type* end)=
=20
>>>>> constructors for both types. <rant>Or it should be possible to create=
=20
>>>>> initializer_list explicitly from such pair which would solve this iss=
ue=20
>>>>> universally.</rant>
>>>>>
>>>> Okay, though initializer_list is not compile-time sized.
>>>> =20
>>>>
>>>>> >>> Furthermore, bounds and index essentially represent a=20
>>>>> >>> fixed-size discrete vector type, i.e. an augmented interface for=
=20
>>>>> std::array.=20
>>>>> >>> Arguably the interface of std::array should just be extended to=
=20
>>>>> add=20
>>>>> >>> component-wise operators instead.  Also, a much more comprehensiv=
e=20
>>>>> set of=20
>>>>> >>> component-wise operations should be provided.  A statically-sized=
=20
>>>>> vector=20
>>>>> >>> type is sorely needed in C++, but it does not make sense to=20
>>>>> standardize=20
>>>>> >>> these limited, single-purposes types when they could be, and=20
>>>>> should be, much=20
>>>>> >>> more general.=20
>>>>> >>
>>>>> >> We don't necessarily want to go for the most general possible type=
=20
>>>>> all at once
>>>>> >
>>>>> > Certainly there is a large design space, but that is a reason to be=
=20
>>>>> cautious about standardizing anything. [...]
>>>>>
>>>>> There are two separate issue raised here:
>>>>> - Why novel types -- this is primarily to introduce "vocabulary" type=
s=20
>>>>> and allow to discriminate index and bounds, as they have different=20
>>>>> semantics, as discussed before. This was also touched upon in the=20
>>>>> previously referred N3851, Appendix, II.
>>>>> - Why so little functionality -- I agree with Jeffrey on this, and I=
=20
>>>>> have described more of the philosophy in the introduction. I would be=
=20
>>>>> interested however what exactly you mean by "a much more comprehensiv=
e set=20
>>>>> of component-wise operations".
>>>>>
>>>> Almost anything could be useful (and I am thinking of the perspective=
=20
>>>> of a general fixed-size vector type, but these all apply to index/boun=
ds as=20
>>>> well), but some particular examples: min, max, <, <=3D, =3D=3D, !=3D, =
>=3D, >.  The=20
>>>> relational operations need to return a vector of bool, which isn't=20
>>>> compatible with index/bounds currently since they aren't parameterized=
 by=20
>>>> the type.  Obviously, though, it wouldn't make sense to call them inde=
x or=20
>>>> bounds if they are parameterized by a type.
>>>> =20
>>>>
>>>>> Having said that, I assume this is something that can be added later=
=20
>>>>> as a pure extension, correct?
>>>>>
>>>> Some of them, like min and max, could be unintrusive, though neither=
=20
>>>> index nor bounds would be a particularly meaningful choice as the retu=
rn=20
>>>> type.
>>>> =20
>>>>
>>>>> > Given the long turn around time for revisions to C++
>>>>>
>>>>> The Committee is certainly trying to get better at quicker iterations=
,=20
>>>>> let's not be discouraged by the ghosts of the past...
>>>>>
>>>>> > Other omissions from index and bounds include:
>>>>> >  1. no data() access to the components
>>>>> >  2. no iterators over components for index or bound
>>>>>
>>>>> index and bounds are not containers and should not be used as such.=
=20
>>>>> For the limited number of scenario where I want to use/modify indeter=
minate=20
>>>>> number of components, it was always sufficient for me to use a raw lo=
op,=20
>>>>> and operator[]...
>>>>> In case I'm wrong, these as well should be easy to add later as=20
>>>>> extensions.
>>>>>
>>>>> > for_each(x_array, y_array, x_array.bounds(), [&](auto &x, auto &y,=
=20
>>>>> auto pos) {
>>>>> >   if (x !=3D y) std::cout << "mismatch at position " << pos <<=20
>>>>> std::endl;
>>>>> > });
>>>>>
>>>>> I assume the idea here is that such "for_each" uses begin(X), end(X)=
=20
>>>>> for all provided arguments, passing dereferenced iterators to the fun=
ction=20
>>>>> object. If so, I do not see how the current semantics of bounds_itera=
tor=20
>>>>> would get into way here? It should just work as is, no?
>>>>>
>>>> The idea is that it would generate N nested for loops for N-dimensiona=
l=20
>>>> array views, rather than an less efficient single for loop.
>>>> =20
>>>>
>>>>> Actually, it should be possible to write the following with just the=
=20
>>>>> current proposal and the current standard for_each:
>>>>>  auto x_av =3D array_view<N>{x_array};
>>>>>  auto y_av =3D array_view<N>{y_array};
>>>>>  for_each(begin(x_av.bounds()), end(x_av.bounds()), [&](index<N> pos)=
=20
>>>>> {
>>>>>   if(x_av[pos] !=3D y_av[pos]) std::cout << "mismatch at position " <=
<=20
>>>>> pos << std::endl;
>>>>>  });
>>>>>
>>>> Yes, but note that the iteration over bounds is more expensive and the=
=20
>>>> multiplication with all of the strides has to happen for every positio=
n.
>>>> =20
>>>>
>>>>> > From my perspective, the only way to properly explore this design=
=20
>>>>> space for multidimensional arrays/containers/ranges is through an act=
ively=20
>>>>> developed and widely used open source library.
>>>>> Our (Microsoft) prototype implementation is in the pipeline to be=20
>>>>> published as an open source project. It should happen really soon, an=
d I=20
>>>>> hope it will help to convey the discussed ideas.
>>>>>
>>>>
>>>> That's good news.  I think the best library is likely to be produced i=
f=20
>>>> the users of the library and the developers of the library are one and=
 the=20
>>>> same.  Issues become apparent and the library interface can be tweaked=
 to=20
>>>> correct them very quickly that way.
>>>> =20
>>>  --=20
>>
>> ---=20
>> You received this message because you are subscribed to a topic in the=
=20
>> Google Groups "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this topic, visit=20
>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/xzb1d5KUxMU=
/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, send an email to=20
>> std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>

--=20

---=20
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 e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_716_988142105.1415999837544
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I think that's convoluting the idea I'm trying to present =
here; the casting point your making... seems to be orthognal to what I'm tr=
ying to say (not to mention... dangerous/broken to implement? Changing the =
way a <i>std::array</i> dereferences would break code everywhere, especiall=
y code that takes a pointer to an array of std::array's (e.g., a vector of =
specifically-sized <i>std::array</i>s) that suddenly behaved as if it was c=
alling operator[] inside of the pointed-to T? That's not a very good idea, =
I don't think).<br><br>That aside, the use case here is being able to nail =
down as many pieces of computation to the compiler as possible: array_view&=
lt;T, ...&gt; and strided_array_view&lt;T, ...&gt; are analogous to a c-sty=
le or std::array-style declarations, with the benefit of providing the dime=
nsions at compile-time. This allows a constexpr operator[] to throw out all=
 of the multiplication and index caluclations to get to exact target index =
exactly before the program runs and instead becomes direct access to the me=
mory of interest; this becomes a particularly interesting case for me as an=
y special optimizations like SIMD can be seen ahead of time by the compiler=
 and substituted in, since it can view those indices ahead of time and know=
 the offsets.<br><br>However, I'm not sure if that's already possible with =
just a constexpr-enabled array_view that takes its dimensions, strides and =
bounds at runtime. I have already written a buffer_view&lt;T, dimension&gt;=
 in my own code based on the proposal paper presented, and then also wrote =
an array_view and strided_array_view with compile-time strides and bounds. =
My current compiler (VC++) chokes on constexpr, so I mostly wanted to ask a=
bout it here, if anyone else had a similar idea.<br><br>On Friday, November=
 14, 2014 3:51:54 PM UTC-5, Jeremy Maitin-Shepard wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr">If the size is known at compil=
e time, an actual reference to std::array (or a multi-dimensional static-si=
zed array counterpart) would be much better, as this eliminates the need fo=
r an extra type, and makes reference decay do the right thing.&nbsp; If the=
 current language rules do not permit the casting of an arbitrary pointer T=
 *x where [x, x+size) is a valid range, to be a pointer to std::array&lt;T,=
size&gt;*, then I think the language rules should be changed, as this is cl=
early extremely useful and any loss of optimization possibilities are proba=
bly minimal.<br></div><div><br><div class=3D"gmail_quote">On Fri, Nov 14, 2=
014 at 12:29 PM,  <span dir=3D"ltr">&lt;<a href=3D"javascript:" target=3D"_=
blank" gdf-obfuscated-mailto=3D"EY36l3K-ekcJ" onmousedown=3D"this.href=3D'j=
avascript:';return true;" onclick=3D"this.href=3D'javascript:';return true;=
">phdoft...@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr">As a small addition, has anyone considered perhaps call=
ing the class <div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word">=
<code><div><span style=3D"color:#000">buffer_view</span><span style=3D"colo=
r:#660">&lt;</span><span style=3D"color:#008">typename</span><span style=3D=
"color:#000"> T</span><span style=3D"color:#660">,</span><span style=3D"col=
or:#000"> size_type dimensions</span><span style=3D"color:#660">&gt;</span>=
</div></code></div><br> and then leaving the name <i>array_view</i> for a c=
ompile-time version of this class (to match std::array)?<br><br>I don't kno=
w if a fully constexpr-qualified version of the buffer_view class will have=
 the same benefit as a compile-time defined <div style=3D"background-color:=
rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wi=
dth:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">array_v=
iew</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">=
typename</span><span style=3D"color:#000"> T</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> size_type</span><span style=3D"color=
:#660">...</span><span style=3D"color:#000"> dimension_sizes</span><span st=
yle=3D"color:#660">&gt;</span></div></code></div><br>class (with <i>strided=
</i> variants for buffer_view and array_view).<div><div><br><br>On Friday, =
June 27, 2014 1:00:54 AM UTC-4, =C5=81ukasz Mendakiewicz wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><p>I do understand your ration=
ale in many of the points you are raising, and I am aware of other existing=
 libraries, which in some cases made different design decisions. However ma=
ny of the choices are mutually exclusive and in my opinion it is impossible=
 to converge on the "single best design". Many of the design decisions in o=
ur proposal are also compromises.</p><p>I disagree with your judgment that =
we should strive to find an ultimate solution before moving forward with an=
y proposal. Lack of array_view or a similar type is clearly a gap in C++ St=
andard, which many libraries are addressing in different ways. We took the =
first stab in trying to address this deficiency with putting forward the ty=
pe we are familiar with, have worked with successfully for over 2 years, an=
d in the process we were also fixing all issues we were aware of. It surely=
 is not rock solid -- nothing is -- and many use-cases might have benefit f=
rom tailoring details differently to cater each of them, but we have to sta=
rt somewhere.</p><div>Importantly, we are not "standardizing" array_view ye=
t. If it passes LWG voting on the next Committee meeting it will be merely =
appended to one of TSs (unless anything changes, this should be Library Fun=
damentals TS) and on track to be considered for C++17. The three years lead=
 time is intended exactly to gather the wider practical experience you are =
concerned about.</div><div><br></div><div>I hope this helps to clarify our =
position.</div><div><br>On Monday, June 16, 2014 5:49:39 PM UTC-7, Jeremy M=
aitin-Shepard wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);bord=
er-left-width:1px;border-left-style:solid"><div dir=3D"ltr">On Sun, Jun 15,=
 2014 at 9:38 PM, =C5=81ukasz Mendakiewicz <span dir=3D"ltr">&lt;<a>l.menda=
....@live.com</a>&gt;</span> wrote:<br><div><div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding=
-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-l=
eft-style:solid"><div dir=3D"ltr"><p>Thank you Jeffrey for adding me on the=
 thread and for your initial response -- which I almost universally agree w=
ith.</p>
<p>Jeremy, thank you for your detailed feedback. First, I believe that most=
 of the disagreement stems from the approach to the proposal. You've commen=
ted&nbsp;that "it doesn't make sense to standardize a partial solution; bet=
ter to work out a good, complete interface outside the standard". This is o=
pposite to the "crawl, walk, run" philosophy we have taken when writing thi=
s document up. We recognize that we have only explored some parts of the de=
sign space, because as you have rightly observed our experience is limited =
to C++ AMP, which constitutes only a specific data parallel approach to alg=
orithms. Of course we believe that this is a solid foundation that can be g=
eneralized and built upon, hence the proposal. But we deliberately avoided =
any design decisions which may be controversial or result in a prolonged tu=
g of war, instead intending for subsequent proposals (not necessarily autho=
red by us) to fill the gaps. Certainly, should anything being proposed now =
be a possible hindrance for any reasonable extension, it must be addressed =
sooner than later, however I think that none of the lacks pointed by you be=
long to this category.</p>
</div></blockquote><div>I think it is basically impossible to nail down eve=
n a "minimal" interface without considering the design of a complete librar=
y.&nbsp; If you looked at 10 different, widely-used C++ multidimensional ar=
ray libraries and saw that all of their interfaces shared a given attribute=
, then standardizing that attribute of the interface would likely be a safe=
 choice.&nbsp; Obviously that is not the case here, though.<br>
<br>Some examples of design options:<br></div><div>- Make array_view parame=
terized by the pointer type, rather than the value type.&nbsp; This allows =
it to hold smart pointers of various types, or a pointer that represents GP=
U memory, or a smart pointer that represents GPU memory, etc.&nbsp; If the =
pointer is to GPU memory, reading and writing won't work (and won't be allo=
wed at compile-time), but the indexing, slicing, sectioning and other opera=
tions on the array_view representation itself can still be used.&nbsp; This=
 is the decision I took in my own in-house library.&nbsp; Allowing array_vi=
ew to hold a smart pointer means you don't need a separate type to represen=
t an array_view with ownership.&nbsp; (Sectioning and slicing produces a re=
sult with the pointer decayed to a regular pointer.)&nbsp; You can also use=
 a __restrict__ pointer for an array_view type used as a function parameter=
 to indicate lack of aliasing.<br>
<br></div><div>- Make bounds and index just generic fixed-size vector types=
..&nbsp; In this case iterators on bounds should iterate over the components=
, rather than iterate over coordinates within the bounds.<br></div><div>&nb=
sp;<br>
</div><div>- More generally, the proposal distinguishes between array_view =
and strided_array_view, but doesn't allow for more fine-grained information=
 to be provided at compile time, such as the number of trailing contiguous =
dimensions, alignment information, etc.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><div><p>&gt;&gt;&gt; Some particula=
r issues with the proposed design include: <br>&gt;&gt;&gt; <br>
&gt;&gt;&gt; - No iterators are provided for array_view or strided_array_vi=
ew, a clear <br>&gt;&gt;&gt; omission in the interface.&nbsp; For a multidi=
mensional array, there are two <br>&gt;&gt;&gt; obvious types of iteration =
that may be desired: <br>
&gt;&gt;&gt;&nbsp;&nbsp; 1. iterating over just the first dimension; <br>&g=
t;&gt;&gt;&nbsp;&nbsp; 2. iterating over a flat view of all of the elements=
..&nbsp; For a strided <br>&gt;&gt;&gt; array, iterating over a flat view ca=
nnot be done efficiently without <br>
&gt;&gt;&gt; segmented/hierarchical iterators. <br>&gt;&gt;&gt;&nbsp;&nbsp;=
 Which of these should be the default (i.e. provided through begin() and <b=
r>&gt;&gt;&gt; end() rather than through some adaptor) is not clear, <br>&g=
t;&gt;<br>
&gt;&gt; From the Zen of Python, "In the face of ambiguity, refuse the <br>=
&gt;&gt; temptation to guess." <br>&gt;<br>&gt; That's true, but no adaptor=
s to provide the functionality unambiguously are provided either.&nbsp; For=
 the particular case of a one-dimensional array, there is no ambiguity, and=
 not being able to easily use array_view with standard algorithms or range-=
based for is a serious usability issue.&nbsp; This will only become worse i=
f/when standard algorithm overloads that take ranges rather than iterator p=
airs are added.</p>
</div><p>To the list of possible alternatives, I would add an option that w=
as proposed somewhere in the prior discussion on the proposal -- "hierarchi=
cal" array_view/elemental iterator, i.e. an iterator that for array_view&lt=
;T, Rank&gt; with Rank &gt; 1 iterates over array_view&lt;T, Rank-1&gt;; an=
d over T for Rank =3D=3D 1.<br>
</p></div></blockquote><div>Yes, that is a better way of expressing what I =
meant by "iterating over just the first dimension".&nbsp; I believe this ma=
kes the most sense, but then it becomes desirable to have size() be the siz=
e of the first dimension for consistency with the iterators, and instead ad=
d a num_elements() that returns the total number of elements.&nbsp; The cor=
rect definition of size() is hard to decide without figuring out how iterat=
ors should work.<br>
<br></div><div>The other issue is that if the iterators are hierarchical, y=
ou need a new hierarchical for_each that effectively expands to N nested fo=
r loops for N-dimensional arrays and which can operate on multiple arrays (=
of the same size).&nbsp; This way you can express element-wise operations w=
ithout any overhead.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><p>It is however worth pointing out=
 that in the first round of review with LEWG at Issaquah meeting, the vocal=
 unchallenged feedback for iterators was "I do not want iterators for the v=
iews", thus we did not put much effort into contemplating adding any. Even =
though the choice for Rank =3D=3D 1 is "obvious", we consider this a corner=
 case for array_view, and would rather have a holistic approach.<br>
There remains the possibility to add some form of the iterator as a future =
extension.</p></div></blockquote><div>Well, you can take my comments as a c=
hallenge to that view.&nbsp; Rank =3D=3D 1 may be a "corner" case, but is l=
ikely to be used more frequently than all other cases combined.&nbsp; A 1-d=
imensional array view that can't be used with for-range loops, boost (or st=
d?) range adapters, etc. is a non-starter.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><div><p>&gt;&gt;&gt; - No data() ac=
cess member for strided_array_view.&nbsp; This is presumably <br>
&gt;&gt;&gt; omitted because the memory is non-contiguous, but given that <=
br>&gt;&gt;&gt; strided_array_view is a thin wrapper, there has to be a con=
venient way to <br>&gt;&gt;&gt; get at the underlying memory. <br>&gt;&gt;<=
br>
&gt;&gt; Why "has to"? <br>&gt;<br>&gt; Because the user might want to conv=
ert the array to another representation for use by another piece of code/li=
brary, e.g. FFTW or Eigen, CUDA memcpy, etc.&nbsp; Under the proposed inter=
face, for a 3-dimensional stided array view, you have to use &amp;arr[0][0]=
[0].&nbsp; This is even worse than having to do &amp;vec[0] for std::vector=
, since the same expression cannot be used independent of the dimensionalit=
y.</p>
</div><p>data() on strided_array_view could be harmful, as there is no guar=
antee of contiguity, which a developer / function template might assume. Pl=
ease note that for every other case in the Standard, the range [data(), dat=
a()+size()) is valid/safe, thus providing other semantics here would be dub=
ious.<br>
Granted, one can perform &amp;arr[0][0][0] and run afoul, but that is no di=
fferent than e.g. &amp;my_list.front().<br>It could be possible to provide =
"unsafe_data()" interface, which would have to be consumed along with strid=
e(), however I do not see much benefit here over just using the "proper" in=
terface -- bounds() and operator[]().</p>
</div></blockquote><div>Calling it noncontiguous_data() is fine, though cer=
tainly then array_view should have an noncontiguous_data() (in addition to =
data()) as well for consistency.&nbsp; I don't think unsafe_data is really =
the right name, though the functionality is more important than the name.&n=
bsp; &amp;arr[0][0][0] has the disadvantage that it is more verbose and doe=
sn't allow for writing generic code that works with any number of dimension=
s.&nbsp; Just using the "proper" interface isn't a solution.&nbsp; A fundam=
ental component like multidimensional arrays cannot be a "walled garden".&n=
bsp; The (pointer, bounds, strides) representation, which numerous other li=
braries like FFTW use as well, should be transparent.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><p></p><div>&gt;&gt;&gt; - Slicing =
is limited: it is not possible to take a slice in a dimension <br>
&gt;&gt;&gt; other than the first. <br>&gt;&gt;<br>&gt;&gt; I think that's =
called "section()". <br>&gt;<br></div>&gt; Well, that takes a "section" but=
 does not reduce the dimensionality like "slice". [...] Certainly there is =
a large design space for general subscripting and it almost certainly requi=
res a fair amount of template metaprogramming, but this is very useful func=
tionality<p>
</p><p>Yes, slicing and sectioning are slightly different. It is however im=
portant to note that slicing in its current form always guarantees the cont=
iguity of the result, thus the return type may be array_view. The more gene=
ral cases (as you are describing) would result in a potentially strided res=
ulting view, which would need to be typed strided_array_view. This is why i=
t is important IMO to distinguish these two cases.<br>
In the current form of the proposal we decided to provide the minimal desig=
n -- only the first version, which in our opinion might be handy for users =
used to C-style multidimensional addressing (i.e. arr[3][1][4] v arr[{3, 1,=
 4}]), which actually you used above :).<br>
The latter generic case can be trivially added as an extension to the inter=
face. I agree it may be useful, and if the current design is accepted for t=
he TS, I encourage you to propose such extension (or nag us for follow ups =
:)).</p>
<div><p>&gt;&gt;&gt; - It is not clear whether it is really useful to have =
bounds and index be <br>&gt;&gt;&gt; separate types (though should probably=
 at least be explicitly convertible to <br>&gt;&gt;&gt; each other). <br>
&gt;&gt;<br>&gt;&gt; It adds a bit of type safety. Adding two bounds, for i=
nstance, doesn't <br>&gt;&gt; make a lot of sense. <br>&gt;<br>&gt; I agree=
 that type safety is in principle useful, but it is impossible to predict w=
hat relationships might hold in any given program, and so there is the ques=
tion of whether the safety it adds is worth the cost of having to explicitl=
y work around it in the cases that it is too restrictive.&nbsp; Certainly i=
f they are separate types there needs to be a way to (explicitly) convert.<=
/p>
</div><p>I agree with both of you :).<br>These are separate types, because =
their meaning and semantics are different. It was also discussed in N3851, =
Appendix, II. The mental model I use for reasoning about them is: index ~ v=
ector and bounds ~ point (more specifically: a zero-bound, axis-aligned rec=
tangle described by its maximum point), which makes the set of available op=
erators apparent.<br>
I understand the explicit conversions between these two types, even though =
not theoretically sound, might be handy in practice and should be added.</p=
></div></blockquote><div>If we follow that logic, a point is a vector from =
the origin.&nbsp; Therefore index should just be Vector&lt;ptrdiff_t,N&gt; =
and bounds&lt;N&gt; could have a Vector&lt;ptrdiff_t,N&gt; member.&nbsp; Ho=
wever, it seems like it would be simpler to just have bounds be Vector&lt;p=
trdiff_t,N&gt; as well and save the trouble of the explicit conversions.&nb=
sp; What type of error does the bounds/index distinction prevent?&nbsp; Mor=
e generally, I am not sure why we shouldn't think of an index as a point as=
 well.&nbsp; If we want the last element in an array x, we have : x.bounds(=
) - 1&nbsp; (or x.bounds() - {1,1, ...}).&nbsp; We want to use this as an i=
ndex, but the current operator definitions would have it be a bounds.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><div><p>&gt; As a specific example,=
 consider if we want to compute the bounds of a valid convolution if we hav=
e an array x and a filter k.&nbsp; The bounds of the result are: x.bounds -=
 k.bounds + 1.&nbsp; None of the arithmetic operators defined in the propos=
al help me with that; I'd just have to write a loop.&nbsp; Even if the arit=
hmetic operators weren't limited by the bounds/index distinction, there wou=
ld still be no way to create a constant-valued vector, i.e. to handle the c=
onstant 1.</p>
</div><p>Explicit conversions would help with the first part, right? I hope=
 you are also not suggesting any such conversion should be implicit?<br>How=
ever I do not really understand what do you mean in the second part, "a con=
stant-valued vector". We purposefully allow to create both bounds&lt;1&gt; =
and index&lt;1&gt; from a scalar; and disallow such operation for Rank &gt;=
 1 (mostly because the semantics are not obvious, e.g. for rank 2, should i=
ndex&lt;2&gt;{16} be {0, 16}, {16, 0} or {16, 16}).<br>
So net-net, in your example you should be able to do: x.bounds - index&lt;2=
&gt;{k.bounds} + {1, 1}. It a little more long-winded, but IMO easier to co=
mprehend than the original.</p></div></blockquote><div>I don't think the ex=
plicit conversion to index adds to the clarity.&nbsp; Also, the problem wit=
h {1, 1} is that it depends on the dimensionality.&nbsp; The interface shou=
ld be designed to be convenient for generic code.&nbsp; I would suggest a S=
calar&lt;T&gt; type generated by a wrapper function scalar, from which boun=
ds and index can be implicitly constructed and which can be used in all of =
the operators.<br>
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;p=
adding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bo=
rder-left-style:solid"><div dir=3D"ltr"><div><p>&gt; Another related issue =
I didn't notice before: the only way to construct an index or bounds type i=
s from an initializer_list.&nbsp; There is no (explicit) conversion from st=
d::array, for instance.&nbsp; It is quite likely that an index or bounds va=
lue would be computed by some other code, that may use a different represen=
tation.</p>
</div><p>Yes, we should add (const value_type* begin, const value_type* end=
) constructors for both types. &lt;rant&gt;Or it should be possible to crea=
te initializer_list explicitly from such pair which would solve this issue =
universally.&lt;/rant&gt;</p>
</div></blockquote><div>Okay, though initializer_list is not compile-time s=
ized.<br></div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204=
);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr"><div>
&gt;&gt;&gt; Furthermore, bounds and index essentially represent a <br>&gt;=
&gt;&gt; fixed-size discrete vector type, i.e. an augmented interface for s=
td::array. <br>&gt;&gt;&gt; Arguably the interface of std::array should jus=
t be extended to add <br>
&gt;&gt;&gt; component-wise operators instead.&nbsp; Also, a much more comp=
rehensive set of <br>&gt;&gt;&gt; component-wise operations should be provi=
ded.&nbsp; A statically-sized vector <br>&gt;&gt;&gt; type is sorely needed=
 in C++, but it does not make sense to standardize <br>
&gt;&gt;&gt; these limited, single-purposes types when they could be, and s=
hould be, much <br>&gt;&gt;&gt; more general. <br>&gt;&gt;<br>&gt;&gt; We d=
on't necessarily want to go for the most general possible type all at once<=
br>
&gt;<br></div>&gt; Certainly there is a large design space, but that is a r=
eason to be cautious about standardizing anything. [...]<p></p><p>There are=
 two separate issue raised here:<br>- Why novel types -- this is primarily =
to introduce "vocabulary" types and allow to discriminate index and bounds,=
 as they have different semantics, as discussed before. This was also touch=
ed upon in the previously referred N3851, Appendix, II.<br>
- Why so little functionality -- I agree with Jeffrey on this, and I have d=
escribed more of the philosophy in the introduction. I would be interested =
however what exactly you mean by "a much more comprehensive set of componen=
t-wise operations".</p>
</div></blockquote><div>Almost anything could be useful (and I am thinking =
of the perspective of a general fixed-size vector type, but these all apply=
 to index/bounds as well), but some particular examples: min, max, &lt;, &l=
t;=3D, =3D=3D, !=3D, &gt;=3D, &gt;.&nbsp; The relational operations need to=
 return a vector of bool, which isn't compatible with index/bounds currentl=
y since they aren't parameterized by the type.&nbsp; Obviously, though, it =
wouldn't make sense to call them index or bounds if they are parameterized =
by a type.<br>
</div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-=
left-width:1px;border-left-style:solid"><div dir=3D"ltr"><p>Having said tha=
t, I assume this is something that can be added later as a pure extension, =
correct?</p>
</div></blockquote><div></div><div>Some of them, like min and max, could be=
 unintrusive, though neither index nor bounds would be a particularly meani=
ngful choice as the return type.<br></div><div>&nbsp;</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border=
-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"=
>
<div dir=3D"ltr"><div><p>&gt; Given the long turn around time for revisions=
 to C++</p></div><p>The Committee is certainly trying to get better at quic=
ker iterations, let's not be discouraged by the ghosts of the past...</p>
<div><p>&gt; Other omissions from index and bounds include:<br>&gt;&nbsp; 1=
.. no data() access to the components<br>&gt;&nbsp; 2. no iterators over com=
ponents for index or bound</p></div><p>index and bounds are not containers =
and should not be used as such. For the limited number of scenario where I =
want to use/modify indeterminate number of components, it was always suffic=
ient for me to use a raw loop, and operator[]...<br>
In case I'm wrong, these as well should be easy to add later as extensions.=
</p><div><p>&gt; for_each(x_array, y_array, x_array.bounds(), [&amp;](auto =
&amp;x, auto &amp;y, auto pos) {<br>&gt;&nbsp;&nbsp; if (x !=3D y) std::cou=
t &lt;&lt; "mismatch at position " &lt;&lt; pos &lt;&lt; std::endl;<br>
&gt; });</p></div><p>I assume the idea here is that such "for_each" uses be=
gin(X), end(X) for all provided arguments, passing dereferenced iterators t=
o the function object. If so, I do not see how the current semantics of bou=
nds_iterator would get into way here? It should just work as is, no?<br>
</p></div></blockquote><div>The idea is that it would generate N nested for=
 loops for N-dimensional array views, rather than an less efficient single =
for loop.<br></div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204=
,204);border-left-width:1px;border-left-style:solid">
<div dir=3D"ltr"><p>Actually, it should be possible to write the following =
with just the current proposal and the current standard for_each:<br>&nbsp;=
auto x_av =3D array_view&lt;N&gt;{x_array};<br>&nbsp;auto y_av =3D array_vi=
ew&lt;N&gt;{y_array};<br>
&nbsp;for_each(begin(x_av.bounds())<u></u><wbr>, end(x_av.bounds()), [&amp;=
](index&lt;N&gt; pos) {<br>&nbsp; if(x_av[pos] !=3D y_av[pos]) std::cout &l=
t;&lt; "mismatch at position " &lt;&lt; pos &lt;&lt; std::endl;<br>&nbsp;})=
;</p></div></blockquote>
<div>Yes, but note that the iteration over bounds is more expensive and the=
 multiplication with all of the strides has to happen for every position.<b=
r></div><div>&nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);borde=
r-left-width:1px;border-left-style:solid">
<div dir=3D"ltr"><p>&gt; From my perspective, the only way to properly expl=
ore this design space for multidimensional arrays/containers/ranges is thro=
ugh an actively developed and widely used open source library.</p><div>Our =
(Microsoft) prototype implementation is in the pipeline to be published as =
an open source project. It should happen really soon, and I hope it will he=
lp to convey the discussed ideas.</div>
</div></blockquote><div><br></div><div>That's good news.&nbsp; I think the =
best library is likely to be produced if the users of the library and the d=
evelopers of the library are one and the same.&nbsp; Issues become apparent=
 and the library interface can be tweaked to correct them very quickly that=
 way.<br>
</div></div></div></div>
</blockquote></div></blockquote></div></div></div><div><div>

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/xzb1d5KUxMU/unsubscribe" target=3D"_blan=
k" onmousedown=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/top=
ic/std-proposals/xzb1d5KUxMU/unsubscribe';return true;" onclick=3D"this.hre=
f=3D'https://groups.google.com/a/isocpp.org/d/topic/std-proposals/xzb1d5KUx=
MU/unsubscribe';return true;">https://groups.google.com/a/<wbr>isocpp.org/d=
/topic/std-<wbr>proposals/xzb1d5KUxMU/<wbr>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"EY36l3K-ekcJ" o=
nmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"EY36l3K-ekcJ" onmousedown=3D"this.href=3D'java=
script:';return true;" onclick=3D"this.href=3D'javascript:';return true;">s=
td-pr...@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank" onmousedown=3D"this.href=3D'http://groups=
..google.com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"thi=
s.href=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';retur=
n true;">http://groups.google.com/a/<wbr>isocpp.org/group/std-<wbr>proposal=
s/</a>.<br>
</div></div></blockquote></div><br></div>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_716_988142105.1415999837544--

.
