Topic: [RFC] array_view with byte stride
Author: Maxim Yanchenko <maxim.yanchenko@gmail.com>
Date: Tue, 28 Mar 2017 01:10:03 +0800
Raw View
--001a113d125c78069d054bb96c5d
Content-Type: text/plain; charset=UTF-8
Good day to everyone,
I checked the existing proposals regarding array_view (including the
multi-dimensional and strided ones) and I found none that would support
byte stride (please correct me if I missed one, apologies in advance).
I have my own custom array view written long time ago which I use a lot and
found it extremely convenient, and it differs from the proposed array_view
by having an additional runtime parameter byte_stride (defaulted to
sizeof(T) to have usual array_view by default).
The byte_stride is not part of the type, so the type is still the same
array_view<class
T, int Rank=1> and you can use it for both contiguous arrays and byte-strided
arrays.
So the constructor looks like this (for 1D array view):
array_view( T* ptr, size_t size, size_t byte_stride = sizeof(T) );
*Motivation*
In scientific/financial calculations one often has arrays of sets of
parameters, i.e. arrays of structs:
struct BasicData {
int data1;
int data2;
};
BasicData barr[50];
It's also not unusual to have extended versions of algorithms that use
additional parameters on top of the generic ones (or save additional data
on top of the common one).
The natural way of dealing with this is just inheriting from the basic
struct and make an array of the derived struct:
struct ExtendedData : BasicData {
int data3;
};
ExtendedData earr[50];
this way you can access common and extended data the same way without
changing your code (and you can freely move parameters from derived struct
to the base and back, without affecting the specialized code that uses
them):
earr.data1[i] = earr.data2[i] * earr.data3[i];
The problem here is that now even the code that doesn't need extended data
(like ones gathering common statistics or statuses) and would happily run
on just basic data (and therefore could have been factored out to the
common unspecialized codebase)
void common_processing(array_view<BasicData>);
Such a function can't run because there is no array of basic params
anymore, they are hidden inside the bigger extended params struct, and
there is currently no way to get an array_view<BasicData> out of earr.
Strided array_view won't help because sizeof(BasicData) is 2*sizeof(int),
while sizeof(ExtendedData) is 3*sizeof(int) - so strides of sizeof(BasicData
) won't work.
Also, there can be a plugin-like architecture of the program so the host
wouldn't even know the type ExtendedData that exists only in the plugin but
still could access BasicData owned by the plugin if there was a way to
construct
array_view<BasicData>.
All the above is easily achievable with a byte-strided array_view.
Another example: think of BasicData as RGB and ExtendedData as RGBA/ARGB:
you could have an array_view<RGB> over an RGBA file and an RGB file and
even an ARGB file, agnostically - they will only differ in their byte_stride
value.
Here are the use cases (1D, for simplicity):
*1) Use as a normal array_view:*
struct B {
int x,y;
};
B *pb = new B[50];
array_view<B> av( pb, 50 ); // byte_stride is defaulted to sizeof(B)
*2) view of an array of a derived class D as an array of base class B:*
struct B {
int x,y;
};
struct D: B {
int a;
};
D *pd = new D[50];
array_view<B> av_b( pd, 50, sizeof(D) );
(pd automatically converted to B*, sizeof(B) == 2*sizeof(int), sizeof(D) ==
3*sizeof(int) so usual integer stride won't work here because sizeof(D) is
not a multiple of sizeof(B))
to avoid mistakes, an obvious helper function array_view_by_base() is
provided (it also checks static_assert(std::is_base_of_v<B,D>)):
array_view<B> av_b = array_view_by_base<B>( pd, 50 );
*3) Member view ("array" of field b):*
struct B {
int x,y;
};
struct C {
int a;
B b;
};
C *pc = new C[50];
array_view<B> av_b( &pc[0].b, 50, sizeof(C) );
array_view<int> av_y( &pc[0].b.y, 50, sizeof(C) );
Again, to avoid mistakes, a helper function array_view_by_member() is
provided:
array_view<B> av_b = array_view_by_member( pc, &C::b, 50 ); // both D and
B are deduced from the arguments
Unfortunately, there is currently no way in C++ to have a nested
pointer-to-member so it's impossible to write something like &C::b::y. This
can be emulated, to some extent, by providing a tuple like (&C::b, &B::y)
but it's not much more readable than the unsafe version. So the safe
version for av_y would be:
array_view<int> av_y = array_view_by_member( pc, std::make_tuple(&C::b,
&B::y), 50 ); // both D and int are deduced from the arguments
*4) Strided views for all the cases above*:
Just call the constructor with stride*sizeof(D) instead of just sizeof(D)
*Note 1:* when the argument p above is not a plain pointer but a container
that knows its size (via std::size - think of std::vector, std::array, or
even another array_view) then you don't need to provide the size manually:
std::vector<B> vb;
array_view<B> av_b( vb );
std::vector<D> vd;
array_view<B> av_b = array_view_by_base<B>( vd );
std::vector<C> vc;
array_view<B> av_b = array_view_by_member( vc, &C::b );
*Note 2:* advantage over some other proposals is in the uniform type
array_view<T,Rank> that doesn't depend on the "continuousness" (unlike
n4177 where strided view is a separate type strided_array_view).
For those who need to know if the view is contiguous (for example, to do a
bulk memcpy instead of element-wise copying) there is a member function bool
continuous() const provided that just checks if sizeof(T)==byte_stride.
*Note 3:* array_view supports default construction and assignment (this is
necessary for the cases when we have a view in the host program, then we
load a plugin, attach to its memory, and initialized our array_view to look
at the plugin's memory, and then we can unload the plugin and load another,
with a different derived type, and reinitialized our array_view again).
Comments?
If there is an agreement that it would be good to have (from my experience,
it is) I'll write a formal proposal.
Thanks everyone,
Yours sincerely,
Maxim Yanchenko
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com.
--001a113d125c78069d054bb96c5d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div><div>Good day to everyone,<br><br=
>I checked the existing proposals regarding <span style=3D"font-family:mono=
space,monospace">array_view</span> (including the multi-dimensional and str=
ided ones) and I found none that would support byte stride (please correct =
me if I missed one, apologies in advance).<br></div>I have my own custom ar=
ray view written long time ago which I use a lot and found it extremely con=
venient, and it differs from the proposed <span style=3D"font-family:monosp=
ace,monospace">array_view</span> by having an additional runtime parameter =
<span style=3D"font-family:monospace,monospace">byte_stride</span> (default=
ed to <span style=3D"font-family:monospace,monospace">sizeof(T)</span> to h=
ave usual <span style=3D"font-family:monospace,monospace">array_view</span>=
by default).<br></div>The <span style=3D"font-family:monospace,monospace">=
byte_stride</span> is not part of the type, so the type is still the same <=
span style=3D"font-family:monospace,monospace">array_view<class T, int R=
ank=3D1></span><span style=3D"font-family:arial,helvetica,sans-serif"> a=
nd</span> you can use it for both contiguous arrays and <span style=3D"font=
-family:arial,helvetica,sans-serif">byte-strided </span>arrays.<br><br></di=
v><div>So the constructor looks like this (for 1D array view): <br></div><d=
iv><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,mon=
ospace">array_view( T* ptr, size_t size, size_t byte_stride =3D sizeof(T) )=
;</span><br></div><br></div><div><b>Motivation</b><br></div><div>In scienti=
fic/financial calculations one often has arrays of sets of parameters, i.e.=
arrays of structs:<br></div><div style=3D"margin-left:40px"><span style=3D=
"font-family:monospace,monospace">struct BasicData {<br></span></div><div s=
tyle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">=
=C2=A0 int data1;<br></span></div><div style=3D"margin-left:40px"><span sty=
le=3D"font-family:monospace,monospace">=C2=A0 int data2;<br></span></div><d=
iv style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospac=
e">};<br></span><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace">BasicData </span>barr[50]; </span></di=
v><div>It's also not unusual to have extended versions of algorithms th=
at use additional parameters on top of the generic ones (or save additional=
data on top of the common one).<br></div><div>The natural way of dealing w=
ith this is just inheriting from the basic struct and make an array of the =
derived struct:<br></div><div style=3D"margin-left:40px"><span style=3D"fon=
t-family:monospace,monospace">struct </span><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace">ExtendedDa=
ta </span><span style=3D"font-family:arial,helvetica,sans-serif"></span>: <=
/span><span style=3D"font-family:monospace,monospace"><span style=3D"font-f=
amily:monospace,monospace">BasicData </span>{<br></span></div><div style=3D=
"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 i=
nt data3;<br></span></div><div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">};<br></span><span style=3D"font-famil=
y:monospace,monospace"><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">ExtendedData e</span></span>arr=
[50];</span><br></div> this way you can access common and extended data the=
same way=20
without changing your code (and you can freely move parameters from=20
derived struct to the base and back, without affecting the specialized=20
code that uses them):<br></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">earr.data1[i] =3D earr.data2[i] * earr=
..data3[i];<br><br></span></div><div>The problem here is that now even the c=
ode that doesn't need extended data (like ones gathering common statist=
ics or statuses) and would happily run on just basic data (and therefore co=
uld have been factored out to the common unspecialized codebase)<br><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">vo=
id common_processing(array_view<</span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace">BasicData</s=
pan>>);</span><br></div>Such a function can't run because there is n=
o array of basic params anymore, they are hidden inside the bigger extended=
params struct, and there is currently no way to get an <span style=3D"font=
-family:monospace,monospace">array_view<BasicData></span> out of <spa=
n style=3D"font-family:monospace,monospace">earr</span>.<br></div><div>Stri=
ded array_view won't help because <span style=3D"font-family:monospace,=
monospace">sizeof(BasicData) </span><span style=3D"font-family:arial,helvet=
ica,sans-serif">is </span><span style=3D"font-family:monospace,monospace">2=
*sizeof(int), while sizeof(</span><span style=3D"font-family:monospace,mono=
space">ExtendedData</span><span style=3D"font-family:arial,helvetica,sans-s=
erif"></span><span style=3D"font-family:monospace,monospace">) </span><span=
style=3D"font-family:arial,helvetica,sans-serif">is </span><span style=3D"=
font-family:monospace,monospace">3*sizeof(int)</span><span style=3D"font-fa=
mily:arial,helvetica,sans-serif"> - so strides of </span><span style=3D"fon=
t-family:monospace,monospace">sizeof(</span><span style=3D"font-family:mono=
space,monospace">BasicData</span><span style=3D"font-family:monospace,monos=
pace">)</span><span style=3D"font-family:arial,helvetica,sans-serif"> won&#=
39;t work.</span><span style=3D"font-family:monospace,monospace"><br></span=
></div><div><br></div><div>Also, there can be a plugin-like architecture of=
the program so the host wouldn't even know the type <span style=3D"fon=
t-family:monospace,monospace">ExtendedData </span><span style=3D"font-famil=
y:arial,helvetica,sans-serif"></span><span style=3D"font-family:arial,helve=
tica,sans-serif">that exists only in the plugin but still could access</spa=
n><span style=3D"font-family:monospace,monospace"> </span><span style=3D"fo=
nt-family:monospace,monospace">BasicData </span><span style=3D"font-family:=
arial,helvetica,sans-serif">owned by the plugin if there was a way to const=
ruct </span><br><span style=3D"font-family:monospace,monospace">array_view&=
lt;</span><span style=3D"font-family:monospace,monospace"><span style=3D"fo=
nt-family:monospace,monospace">BasicData</span>>.</span></div><div><br>A=
ll the above is easily achievable with <span style=3D"font-family:arial,hel=
vetica,sans-serif">a byte-strided </span><span style=3D"font-family:monospa=
ce,monospace">array_view</span>.<br><br><br></div><div>Another example: thi=
nk of <span style=3D"font-family:monospace,monospace">BasicData </span>as<s=
pan style=3D"font-family:monospace,monospace"> RGB </span>and <span style=
=3D"font-family:monospace,monospace">ExtendedData </span><span style=3D"fon=
t-family:arial,helvetica,sans-serif">as<span style=3D"font-family:monospace=
,monospace"> </span></span><span style=3D"font-family:monospace,monospace">=
RGBA/ARGB:</span> you could have an <span style=3D"font-family:monospace,mo=
nospace">array_view<RGB></span> over an RGBA file and an RGB file and=
even an ARGB file, agnostically - they will only differ in their <span sty=
le=3D"font-family:monospace,monospace">byte_stride</span> value.<br><br><br=
></div><div><br></div>Here are the use cases (1D, for simplicity):<br><br><=
/div><div><b>1) Use as a normal <span style=3D"font-family:monospace,monosp=
ace">array_view</span>:</b><br></div><div style=3D"margin-left:40px"><span =
style=3D"font-family:monospace,monospace"><span style=3D"font-family:monosp=
ace,monospace">struct B {<br></span><span style=3D"font-family:monospace,mo=
nospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monospace,mon=
ospace">};<br></span></span><span style=3D"font-family:monospace,monospace"=
>B *pb =3D new B[50];</span></div><div><div style=3D"margin-left:40px"><spa=
n style=3D"font-family:monospace,monospace">array_view<B> av( pb, 50 =
); // byte_stride</span><span style=3D"font-family:arial,helvetica,sans-ser=
if"> is defaulted to</span><span style=3D"font-family:monospace,monospace">=
sizeof(B)</span><br></div><div style=3D"margin-left:40px"><span style=3D"f=
ont-family:monospace,monospace"></span></div><span style=3D"font-family:mon=
ospace,monospace"><br></span></div><b>2) view of an array of a derived clas=
s D as an array of base class B:</b><br></div><span style=3D"font-family:mo=
nospace,monospace"></span></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace"><span style=3D"font-family:monospace,monospace">struct B {<br></s=
pan><span style=3D"font-family:monospace,monospace">=C2=A0 int x,y;<br></sp=
an><span style=3D"font-family:monospace,monospace">};<br></span></span><spa=
n style=3D"font-family:monospace,monospace"></span>struct D: B {<br></span>=
</div><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,=
monospace">=C2=A0 int a;<br>};<br></span></div><div style=3D"margin-left:40=
px"><span style=3D"font-family:monospace,monospace">D *pd =3D new D[50];<br=
></span></div><div><div style=3D"margin-left:40px"><span style=3D"font-fami=
ly:monospace,monospace">array_view<B> av_b( pd, 50, sizeof(D) );<br><=
br></span><span style=3D"font-family:monospace,monospace"></span></div><spa=
n style=3D"font-family:arial,helvetica,sans-serif">(</span><span style=3D"f=
ont-family:monospace,monospace">pd </span><span style=3D"font-family:arial,=
helvetica,sans-serif">automatically converted to </span><span style=3D"font=
-family:monospace,monospace">B*, sizeof(B) =3D=3D 2*sizeof(int), sizeof(D) =
=3D=3D 3*sizeof(int)</span><span style=3D"font-family:arial,helvetica,sans-=
serif"> so usual integer stride won't work here because <span style=3D"=
font-family:monospace,monospace">sizeof(D)</span> is not a multiple of <spa=
n style=3D"font-family:monospace,monospace">sizeof(B)</span>)</span><br><br=
></div><div>to avoid mistakes, an obvious helper function <span style=3D"fo=
nt-family:monospace,monospace">array_view_by_base()</span> is provided (it =
also checks <span style=3D"font-family:monospace,monospace">static_assert(s=
td::is_base_of_v<B,D>)</span>):<br></div><div style=3D"margin-left:40=
px"><span style=3D"font-family:monospace,monospace">array_view<B> av_=
b =3D array_view_by_base<B>( pd, 50 );</span></div><div><br></div><di=
v><b>3) Member view ("array" of field b):</b><br><div style=3D"ma=
rgin-left:40px"><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">struct B {<br></span><span style=3D"font-family:monospace,monospa=
ce">=C2=A0 int x,y;<br></span><span style=3D"font-family:monospace,monospac=
e">};<br></span></span><span style=3D"font-family:monospace,monospace"></sp=
an>struct C {<br></span></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">=C2=A0 int a;</span><br><span style=3D=
"font-family:monospace,monospace"></span></div></div><div style=3D"margin-l=
eft:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 B b;<br></=
span></div><div style=3D"margin-left:40px"><span style=3D"font-family:monos=
pace,monospace">};</span><span style=3D"font-family:monospace,monospace"><b=
r></span><span style=3D"font-family:monospace,monospace"><span style=3D"fon=
t-family:monospace,monospace">C *pc =3D new C[50];<br></span></span></div><=
div style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospa=
ce">array_view<B>=C2=A0=C2=A0 av_b( </span><span style=3D"font-family=
:monospace,monospace"><span style=3D"font-family:monospace,monospace">&=
pc[0].b,=C2=A0=C2=A0 50, sizeof(C) </span>);<br></span></div><div style=3D"=
margin-left:40px"><span style=3D"font-family:monospace,monospace">array_vie=
w<int> av_y( </span><span style=3D"font-family:monospace,monospace"><=
span style=3D"font-family:monospace,monospace">&pc[0].b.y, 50, sizeof(C=
) </span>);<br></span></div><span style=3D"font-family:monospace,monospace"=
></span><span style=3D"font-family:monospace,monospace"><font face=3D"arial=
,helvetica,sans-serif"><br>Again, to avoid mistakes, a helper function </fo=
nt>array_view_by_member()</span><span style=3D"font-family:arial,helvetica,=
sans-serif"> is provided</span>:<br><span style=3D"font-family:monospace,mo=
nospace"></span><div style=3D"margin-left:40px"><span style=3D"font-family:=
monospace,monospace"><span style=3D"font-family:monospace,monospace">array_=
view<B>=C2=A0=C2=A0 av_b =3D array_view_by_member( pc, &C::b, 50 =
);</span></span> // both D and B are deduced from the arguments<br><br></di=
v><div>Unfortunately, there is currently no way in C++ to have a nested poi=
nter-to-member so it's impossible to write something like <span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">&C::b::y</span></span><span style=3D"font-family:arial,helvet=
ica,sans-serif">. This can be emulated, to some extent, by providing a tupl=
e like <span style=3D"font-family:monospace,monospace">(&C::b, &B::=
y)</span> but it's not much more readable than the unsafe version. So t=
he safe version for <span style=3D"font-family:times new roman,serif">av_y<=
/span> would be</span><span style=3D"font-family:times new roman,serif">:</=
span><span style=3D"font-family:monospace,monospace"><span style=3D"font-fa=
mily:monospace,monospace"><br></span></span><div style=3D"margin-left:40px"=
><span style=3D"font-family:monospace,monospace"><span style=3D"font-family=
:monospace,monospace">array_view<int> av_y =3D array_view_by_member( =
pc, std::make_tuple(&C::b,</span></span><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace"><span styl=
e=3D"font-family:arial,helvetica,sans-serif"><span style=3D"font-family:mon=
ospace,monospace"> &B::y)</span></span>, 50 );</span></span> // both D =
and int are deduced from the arguments</div></div><div><br></div><div><b>4)=
Strided views for all the cases above</b>:<br></div><div>Just call the con=
structor with stride*sizeof(D) instead of just sizeof(D)<br></div><div><br>=
<br></div><div><b>Note 1:</b> when the argument p above is not a plain poin=
ter but a container that knows its size (via std::size - think of std::vect=
or, std::array, or even another array_view) then you don't need to prov=
ide the size manually:<br><div style=3D"margin-left:40px"><span style=3D"fo=
nt-family:monospace,monospace">std::vector<B> vb;</span><br><span sty=
le=3D"font-family:monospace,monospace">array_view<B> av_b( vb );</spa=
n><br><span style=3D"font-family:monospace,monospace">std::vector<D> =
vd;</span><br><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace"><span style=3D"font-family:monospace,monospace">array_view<B&g=
t; av_b =3D </span>array_view_by_base<B>( vd );</span></span></span><=
br><span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:monospace,monospace"></s=
pan></span></span><span style=3D"font-family:monospace,monospace"><span sty=
le=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace=
,monospace">std::vector<C> vc;</span><br><span style=3D"font-family:m=
onospace,monospace"><span style=3D"font-family:monospace,monospace"><span s=
tyle=3D"font-family:monospace,monospace"><span style=3D"font-family:monospa=
ce,monospace"></span></span></span></span>array_view<B> av_b =3D </sp=
an></span><span style=3D"font-family:monospace,monospace"><span style=3D"fo=
nt-family:monospace,monospace"><span style=3D"font-family:monospace,monospa=
ce"><span style=3D"font-family:monospace,monospace">array_view_by_member</s=
pan></span></span>( vc</span><span style=3D"font-family:monospace,monospace=
"><span style=3D"font-family:monospace,monospace"><span style=3D"font-famil=
y:monospace,monospace">, &C::b</span></span> );</span><br></div><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace"></=
span></div><span style=3D"font-family:monospace,monospace"><br></span></div=
><div><span style=3D"font-family:arial,helvetica,sans-serif"><b>Note 2:</b>=
advantage over some other proposals is in the uniform type <span style=3D"=
font-family:monospace,monospace">array_view<T,Rank></span> that doesn=
't depend on the "continuousness" (unlike n4177 where strided=
view is a separate type </span><span style=3D"font-family:arial,helvetica,=
sans-serif"><code>strided_array_view</code>). <br>For those who need to kno=
w if the view is contiguous (for example, to do a bulk <span style=3D"font-=
family:monospace,monospace">memcpy</span> instead of element-wise copying) =
there is a member function=C2=A0 <span style=3D"font-family:monospace,monos=
pace">bool continuous() const</span> provided that just checks if <span sty=
le=3D"font-family:monospace,monospace">sizeof(T)=3D=3Dbyte_stride</span>.<b=
r></span><span style=3D"font-family:arial,helvetica,sans-serif"><br></span>=
</div><div><span style=3D"font-family:arial,helvetica,sans-serif"><b>Note 3=
:</b> array_view supports default construction and assignment (this is nece=
ssary for the cases when we have a view in the host program, then we load a=
plugin, attach to its memory, and initialized our array_view to look at th=
e plugin's memory, and then we can unload the plugin and load another, =
with a different derived type, and reinitialized our array_view again).<br>=
<br></span></div><div><span style=3D"font-family:arial,helvetica,sans-serif=
"><br></span></div><div><span style=3D"font-family:arial,helvetica,sans-ser=
if">Comments?<br>If there is </span><span style=3D"font-family:arial,helvet=
ica,sans-serif"><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"></span></span></span>an agreement that=
it would be good to have (from my experience, it is) I'll write a form=
al proposal.<br><br></div><div>Thanks everyone,<br></div><div>Yours sincere=
ly,<br></div><div>Maxim Yanchenko<br></div><div><span style=3D"font-family:=
monospace,monospace"><br></span></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3=
Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_=
%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com</a>.<br />
--001a113d125c78069d054bb96c5d--
.
Author: Jonathan Coe <jonathanbcoe@gmail.com>
Date: Mon, 27 Mar 2017 18:17:53 +0100
Raw View
--001a11416e8c6f1c80054bb988db
Content-Type: text/plain; charset=UTF-8
On 27 March 2017 at 18:10, Maxim Yanchenko <maxim.yanchenko@gmail.com>
wrote:
> Good day to everyone,
>
> I checked the existing proposals regarding array_view (including the
> multi-dimensional and strided ones) and I found none that would support
> byte stride (please correct me if I missed one, apologies in advance).
> I have my own custom array view written long time ago which I use a lot
> and found it extremely convenient, and it differs from the proposed
> array_view by having an additional runtime parameter byte_stride
> (defaulted to sizeof(T) to have usual array_view by default).
> The byte_stride is not part of the type, so the type is still the same array_view<class
> T, int Rank=1> and you can use it for both contiguous arrays and byte-strided
> arrays.
>
> So the constructor looks like this (for 1D array view):
> array_view( T* ptr, size_t size, size_t byte_stride = sizeof(T) );
>
> *Motivation*
> In scientific/financial calculations one often has arrays of sets of
> parameters, i.e. arrays of structs:
> struct BasicData {
> int data1;
> int data2;
> };
> BasicData barr[50];
> It's also not unusual to have extended versions of algorithms that use
> additional parameters on top of the generic ones (or save additional data
> on top of the common one).
> The natural way of dealing with this is just inheriting from the basic
> struct and make an array of the derived struct:
> struct ExtendedData : BasicData {
> int data3;
> };
> ExtendedData earr[50];
> this way you can access common and extended data the same way without
> changing your code (and you can freely move parameters from derived struct
> to the base and back, without affecting the specialized code that uses
> them):
> earr.data1[i] = earr.data2[i] * earr.data3[i];
>
> The problem here is that now even the code that doesn't need extended data
> (like ones gathering common statistics or statuses) and would happily run
> on just basic data (and therefore could have been factored out to the
> common unspecialized codebase)
> void common_processing(array_view<BasicData>);
> Such a function can't run because there is no array of basic params
> anymore, they are hidden inside the bigger extended params struct, and
> there is currently no way to get an array_view<BasicData> out of earr.
> Strided array_view won't help because sizeof(BasicData) is 2*sizeof(int),
> while sizeof(ExtendedData) is 3*sizeof(int) - so strides of sizeof(
> BasicData) won't work.
>
> Also, there can be a plugin-like architecture of the program so the host
> wouldn't even know the type ExtendedData that exists only in the plugin
> but still could access BasicData owned by the plugin if there was a way
> to construct
> array_view<BasicData>.
>
> All the above is easily achievable with a byte-strided array_view.
>
>
> Another example: think of BasicData as RGB and ExtendedData as RGBA/ARGB:
> you could have an array_view<RGB> over an RGBA file and an RGB file and
> even an ARGB file, agnostically - they will only differ in their
> byte_stride value.
>
>
>
> Here are the use cases (1D, for simplicity):
>
> *1) Use as a normal array_view:*
> struct B {
> int x,y;
> };
> B *pb = new B[50];
> array_view<B> av( pb, 50 ); // byte_stride is defaulted to sizeof(B)
>
> *2) view of an array of a derived class D as an array of base class B:*
> struct B {
> int x,y;
> };
> struct D: B {
> int a;
> };
> D *pd = new D[50];
> array_view<B> av_b( pd, 50, sizeof(D) );
>
> (pd automatically converted to B*, sizeof(B) == 2*sizeof(int), sizeof(D)
> == 3*sizeof(int) so usual integer stride won't work here because sizeof(D)
> is not a multiple of sizeof(B))
>
> to avoid mistakes, an obvious helper function array_view_by_base() is
> provided (it also checks static_assert(std::is_base_of_v<B,D>)):
> array_view<B> av_b = array_view_by_base<B>( pd, 50 );
>
> *3) Member view ("array" of field b):*
> struct B {
> int x,y;
> };
> struct C {
> int a;
> B b;
> };
> C *pc = new C[50];
> array_view<B> av_b( &pc[0].b, 50, sizeof(C) );
> array_view<int> av_y( &pc[0].b.y, 50, sizeof(C) );
>
> Again, to avoid mistakes, a helper function array_view_by_member() is
> provided:
> array_view<B> av_b = array_view_by_member( pc, &C::b, 50 ); // both D
> and B are deduced from the arguments
>
> Unfortunately, there is currently no way in C++ to have a nested
> pointer-to-member so it's impossible to write something like &C::b::y.
> This can be emulated, to some extent, by providing a tuple like (&C::b,
> &B::y) but it's not much more readable than the unsafe version. So the
> safe version for av_y would be:
> array_view<int> av_y = array_view_by_member( pc, std::make_tuple(&C::b,
> &B::y), 50 ); // both D and int are deduced from the arguments
>
> *4) Strided views for all the cases above*:
> Just call the constructor with stride*sizeof(D) instead of just sizeof(D)
>
>
> *Note 1:* when the argument p above is not a plain pointer but a
> container that knows its size (via std::size - think of std::vector,
> std::array, or even another array_view) then you don't need to provide the
> size manually:
> std::vector<B> vb;
> array_view<B> av_b( vb );
> std::vector<D> vd;
> array_view<B> av_b = array_view_by_base<B>( vd );
> std::vector<C> vc;
> array_view<B> av_b = array_view_by_member( vc, &C::b );
>
> *Note 2:* advantage over some other proposals is in the uniform type
> array_view<T,Rank> that doesn't depend on the "continuousness" (unlike
> n4177 where strided view is a separate type strided_array_view).
> For those who need to know if the view is contiguous (for example, to do a
> bulk memcpy instead of element-wise copying) there is a member function bool
> continuous() const provided that just checks if sizeof(T)==byte_stride.
>
> *Note 3:* array_view supports default construction and assignment (this
> is necessary for the cases when we have a view in the host program, then we
> load a plugin, attach to its memory, and initialized our array_view to look
> at the plugin's memory, and then we can unload the plugin and load another,
> with a different derived type, and reinitialized our array_view again).
>
>
> Comments?
> If there is an agreement that it would be good to have (from my
> experience, it is) I'll write a formal proposal.
>
>
A byte-strided array_view would lose many of the advantages of memory
contiguity. I'd be inclined to use a struct of array_views rather than a
strided array view of structs.
struct C_view {
array_view<int> as;
array_view<B> bs;
};
I think there are already some proposals in flight to convert vectors of
structs into structs of vectors.
Regards,
Jon
Thanks everyone,
> Yours sincerely,
> Maxim Yanchenko
>
> --
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%
> 3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com.
--001a11416e8c6f1c80054bb988db
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On 27 March 2017 at 18:10, Maxim Yanchenko <span dir=3D"ltr"><<a hre=
f=3D"mailto:maxim.yanchenko@gmail.com" target=3D"_blank">maxim.yanchenko@gm=
ail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,2=
04,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><di=
v><div><div><div><div>Good day to everyone,<br><br>I checked the existing p=
roposals regarding <span style=3D"font-family:monospace,monospace">array_vi=
ew</span> (including the multi-dimensional and strided ones) and I found no=
ne that would support byte stride (please correct me if I missed one, apolo=
gies in advance).<br></div>I have my own custom array view written long tim=
e ago which I use a lot and found it extremely convenient, and it differs f=
rom the proposed <span style=3D"font-family:monospace,monospace">array_view=
</span> by having an additional runtime parameter <span style=3D"font-famil=
y:monospace,monospace">byte_stride</span> (defaulted to <span style=3D"font=
-family:monospace,monospace">sizeof(T)</span> to have usual <span style=3D"=
font-family:monospace,monospace">array_view</span> by default).<br></div>Th=
e <span style=3D"font-family:monospace,monospace">byte_stride</span> is not=
part of the type, so the type is still the same <span style=3D"font-family=
:monospace,monospace">array_view<class T, int Rank=3D1></span><span s=
tyle=3D"font-family:arial,helvetica,sans-serif"> and</span> you can use it =
for both contiguous arrays and <span style=3D"font-family:arial,helvetica,s=
ans-serif">byte-strided </span>arrays.<br><br></div><div>So the constructor=
looks like this (for 1D array view): <br></div><div><div style=3D"margin-l=
eft:40px"><span style=3D"font-family:monospace,monospace">array_view( T* pt=
r, size_t size, size_t byte_stride =3D sizeof(T) );</span><br></div><br></d=
iv><div><b>Motivation</b><br></div><div>In scientific/financial calculation=
s one often has arrays of sets of parameters, i.e. arrays of structs:<br></=
div><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,mo=
nospace">struct BasicData {<br></span></div><div style=3D"margin-left:40px"=
><span style=3D"font-family:monospace,monospace">=C2=A0 int data1;<br></spa=
n></div><div style=3D"margin-left:40px"><span style=3D"font-family:monospac=
e,monospace">=C2=A0 int data2;<br></span></div><div style=3D"margin-left:40=
px"><span style=3D"font-family:monospace,monospace">};<br></span><span styl=
e=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,=
monospace">BasicData </span>barr[50]; </span></div><div>It's also not u=
nusual to have extended versions of algorithms that use additional paramete=
rs on top of the generic ones (or save additional data on top of the common=
one).<br></div><div>The natural way of dealing with this is just inheritin=
g from the basic struct and make an array of the derived struct:<br></div><=
div style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospa=
ce">struct </span><span style=3D"font-family:monospace,monospace"><span sty=
le=3D"font-family:monospace,monospace">ExtendedData </span><span style=3D"f=
ont-family:arial,helvetica,sans-serif"></span>: </span><span style=3D"font-=
family:monospace,monospace"><span style=3D"font-family:monospace,monospace"=
>BasicData </span>{<br></span></div><div style=3D"margin-left:40px"><span s=
tyle=3D"font-family:monospace,monospace">=C2=A0 int data3;<br></span></div>=
<div><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,m=
onospace">};<br></span><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace"><span style=3D"font-family:mono=
space,monospace">ExtendedData e</span></span>arr[50];</span><br></div> this=
way you can access common and extended data the same way=20
without changing your code (and you can freely move parameters from=20
derived struct to the base and back, without affecting the specialized=20
code that uses them):<br></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">earr.data1[i] =3D earr.data2[i] * earr=
..data3[i];<br><br></span></div><div>The problem here is that now even the c=
ode that doesn't need extended data (like ones gathering common statist=
ics or statuses) and would happily run on just basic data (and therefore co=
uld have been factored out to the common unspecialized codebase)<br><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">vo=
id common_processing(array_view<</span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace">B<wbr>asicDa=
ta</span>>);</span><br></div>Such a function can't run because there=
is no array of basic params anymore, they are hidden inside the bigger ext=
ended params struct, and there is currently no way to get an <span style=3D=
"font-family:monospace,monospace">array_view<BasicData></span> out of=
<span style=3D"font-family:monospace,monospace">earr</span>.<br></div><div=
>Strided array_view won't help because <span style=3D"font-family:monos=
pace,monospace">sizeof(BasicData) </span><span style=3D"font-family:arial,h=
elvetica,sans-serif">is </span><span style=3D"font-family:monospace,monospa=
ce">2*sizeof(int), while sizeof(</span><span style=3D"font-family:monospace=
,monospace">ExtendedData</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"></span><span style=3D"font-family:monospace,monospace">) </span>=
<span style=3D"font-family:arial,helvetica,sans-serif">is </span><span styl=
e=3D"font-family:monospace,monospace">3*sizeof(int)</span><span style=3D"fo=
nt-family:arial,helvetica,sans-serif"> - so strides of </span><span style=
=3D"font-family:monospace,monospace">sizeof(</span><span style=3D"font-fami=
ly:monospace,monospace">BasicData</span><span style=3D"font-family:monospac=
e,monospace">)</span><span style=3D"font-family:arial,helvetica,sans-serif"=
> won't work.</span><span style=3D"font-family:monospace,monospace"><br=
></span></div><div><br></div><div>Also, there can be a plugin-like architec=
ture of the program so the host wouldn't even know the type <span style=
=3D"font-family:monospace,monospace">ExtendedData </span><span style=3D"fon=
t-family:arial,helvetica,sans-serif"></span><span style=3D"font-family:aria=
l,helvetica,sans-serif">that exists only in the plugin but still could acce=
ss</span><span style=3D"font-family:monospace,monospace"> </span><span styl=
e=3D"font-family:monospace,monospace">BasicData </span><span style=3D"font-=
family:arial,helvetica,sans-serif">owned by the plugin if there was a way t=
o construct </span><br><span style=3D"font-family:monospace,monospace">arra=
y_view<</span><span style=3D"font-family:monospace,monospace"><span styl=
e=3D"font-family:monospace,monospace">BasicData</span>>.</span></div><di=
v><br>All the above is easily achievable with <span style=3D"font-family:ar=
ial,helvetica,sans-serif">a byte-strided </span><span style=3D"font-family:=
monospace,monospace">array_view</span>.<br><br><br></div><div>Another examp=
le: think of <span style=3D"font-family:monospace,monospace">BasicData </sp=
an>as<span style=3D"font-family:monospace,monospace"> RGB </span>and <span =
style=3D"font-family:monospace,monospace">ExtendedData </span><span style=
=3D"font-family:arial,helvetica,sans-serif">as<span style=3D"font-family:mo=
nospace,monospace"> </span></span><span style=3D"font-family:monospace,mono=
space">RGBA/ARGB:</span> you could have an <span style=3D"font-family:monos=
pace,monospace">array_view<RGB></span> over an RGBA file and an RGB f=
ile and even an ARGB file, agnostically - they will only differ in their <s=
pan style=3D"font-family:monospace,monospace">byte_stride</span> value.<br>=
<br><br></div><div><br></div>Here are the use cases (1D, for simplicity):<b=
r><br></div><div><b>1) Use as a normal <span style=3D"font-family:monospace=
,monospace">array_view</span>:</b><br></div><div style=3D"margin-left:40px"=
><span style=3D"font-family:monospace,monospace"><span style=3D"font-family=
:monospace,monospace">struct B {<br></span><span style=3D"font-family:monos=
pace,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monosp=
ace,monospace">};<br></span></span><span style=3D"font-family:monospace,mon=
ospace">B *pb =3D new B[50];</span></div><div><div style=3D"margin-left:40p=
x"><span style=3D"font-family:monospace,monospace">array_view<B> av( =
pb, 50 ); // byte_stride</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"> is defaulted to</span><span style=3D"font-family:monospace,mono=
space"> sizeof(B)</span><br></div><div style=3D"margin-left:40px"><span sty=
le=3D"font-family:monospace,monospace"></span></div><span style=3D"font-fam=
ily:monospace,monospace"><br></span></div><b>2) view of an array of a deriv=
ed class D as an array of base class B:</b><br></div><span style=3D"font-fa=
mily:monospace,monospace"></span></div><div style=3D"margin-left:40px"><spa=
n style=3D"font-family:monospace,monospace"><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace">struct B {=
<br></span><span style=3D"font-family:monospace,monospace">=C2=A0 int x,y;<=
br></span><span style=3D"font-family:monospace,monospace">};<br></span></sp=
an><span style=3D"font-family:monospace,monospace"></span>struct D: B {<br>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">=C2=A0 int a;<br>};<br></span></div><div style=3D"margin-=
left:40px"><span style=3D"font-family:monospace,monospace">D *pd =3D new D[=
50];<br></span></div><div><div style=3D"margin-left:40px"><span style=3D"fo=
nt-family:monospace,monospace">array_view<B> av_b( pd, 50, sizeof(D) =
);<br><br></span><span style=3D"font-family:monospace,monospace"></span></d=
iv><span style=3D"font-family:arial,helvetica,sans-serif">(</span><span sty=
le=3D"font-family:monospace,monospace">pd </span><span style=3D"font-family=
:arial,helvetica,sans-serif">automatically converted to </span><span style=
=3D"font-family:monospace,monospace">B*, sizeof(B) =3D=3D 2*sizeof(int), si=
zeof(D) =3D=3D 3*sizeof(int)</span><span style=3D"font-family:arial,helveti=
ca,sans-serif"> so usual integer stride won't work here because <span s=
tyle=3D"font-family:monospace,monospace">sizeof(D)</span> is not a multiple=
of <span style=3D"font-family:monospace,monospace">sizeof(B)</span>)</span=
><br><br></div><div>to avoid mistakes, an obvious helper function <span sty=
le=3D"font-family:monospace,monospace">array_view_by_base()</span> is provi=
ded (it also checks <span style=3D"font-family:monospace,monospace">static_=
assert(std::is_base_of_<wbr>v<B,D>)</span>):<br></div><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">array_view=
<B> av_b =3D array_view_by_base<B>( pd, 50 );</span></div><div>=
<br></div><div><b>3) Member view ("array" of field b):</b><br><di=
v style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace=
"><span style=3D"font-family:monospace,monospace"><span style=3D"font-famil=
y:monospace,monospace">struct B {<br></span><span style=3D"font-family:mono=
space,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monos=
pace,monospace">};<br></span></span><span style=3D"font-family:monospace,mo=
nospace"></span>struct C {<br></span></div><div style=3D"margin-left:40px">=
<span style=3D"font-family:monospace,monospace">=C2=A0 int a;</span><br><sp=
an style=3D"font-family:monospace,monospace"></span></div></div><div style=
=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=
=A0 B b;<br></span></div><div style=3D"margin-left:40px"><span style=3D"fon=
t-family:monospace,monospace">};</span><span style=3D"font-family:monospace=
,monospace"><br></span><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">C *pc =3D new C[50];<br></span>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">array_view<B>=C2=A0=C2=A0 av_b( </span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">&pc[0].b,=C2=A0=C2=A0 50, sizeof(C) </span>);<br></span></div=
><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,monos=
pace">array_view<int> av_y( </span><span style=3D"font-family:monospa=
ce,monospace"><span style=3D"font-family:monospace,monospace">&pc[0].b.=
y, 50, sizeof(C) </span>);<br></span></div><span style=3D"font-family:monos=
pace,monospace"></span><span style=3D"font-family:monospace,monospace"><fon=
t face=3D"arial,helvetica,sans-serif"><br>Again, to avoid mistakes, a helpe=
r function </font>array_view_by_member()</span><span style=3D"font-family:a=
rial,helvetica,sans-serif"> is provided</span>:<br><span style=3D"font-fami=
ly:monospace,monospace"></span><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view<B>=C2=A0=C2=A0 av_b =3D array_view_by_member( pc=
, &C::b, 50 );</span></span> // both D and B are deduced from the argum=
ents<br><br></div><div>Unfortunately, there is currently no way in C++ to h=
ave a nested pointer-to-member so it's impossible to write something li=
ke <span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace">&C::b::y</span></span><span style=3D"font-famil=
y:arial,helvetica,sans-serif">. This can be emulated, to some extent, by pr=
oviding a tuple like <span style=3D"font-family:monospace,monospace">(&=
C::b, &B::y)</span> but it's not much more readable than the unsafe=
version. So the safe version for <span style=3D"font-family:'times new=
roman',serif">av_y</span> would be</span><span style=3D"font-family:&#=
39;times new roman',serif">:</span><span style=3D"font-family:monospace=
,monospace"><span style=3D"font-family:monospace,monospace"><br></span></sp=
an><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace">array_view<int&g=
t; av_y =3D array_view_by_member( pc, std::make_tuple(&C::b,</span></sp=
an><span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:arial,helvetica,sans-ser=
if"><span style=3D"font-family:monospace,monospace"> &B::y)</span></spa=
n>, 50 );</span></span> // both D and int are deduced from the arguments</d=
iv></div><div><br></div><div><b>4) Strided views for all the cases above</b=
>:<br></div><div>Just call the constructor with stride*sizeof(D) instead of=
just sizeof(D)<br></div><div><br><br></div><div><b>Note 1:</b> when the ar=
gument p above is not a plain pointer but a container that knows its size (=
via std::size - think of std::vector, std::array, or even another array_vie=
w) then you don't need to provide the size manually:<br><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">std::vecto=
r<B> vb;</span><br><span style=3D"font-family:monospace,monospace">ar=
ray_view<B> av_b( vb );</span><br><span style=3D"font-family:monospac=
e,monospace">std::vector<D> vd;</span><br><span style=3D"font-family:=
monospace,monospace"><span style=3D"font-family:monospace,monospace"><span =
style=3D"font-family:monospace,monospace"><span style=3D"font-family:monosp=
ace,monospace">array_view<B> av_b =3D </span>array_view_by_base<B&=
gt;( vd );</span></span></span><br><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace"><span style=3D"font=
-family:monospace,monospace"></span></span></span><span style=3D"font-famil=
y:monospace,monospace"><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">std::vector<C> vc;</span>=
<br><span style=3D"font-family:monospace,monospace"><span style=3D"font-fam=
ily:monospace,monospace"><span style=3D"font-family:monospace,monospace"><s=
pan style=3D"font-family:monospace,monospace"></span></span></span></span>a=
rray_view<B> av_b =3D </span></span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view_by_member</span></span></span>( vc</span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace"><span style=3D"font-family:monospace,monospace">, &C::b</span=
></span> );</span><br></div><div style=3D"margin-left:40px"><span style=3D"=
font-family:monospace,monospace"></span></div><span style=3D"font-family:mo=
nospace,monospace"><br></span></div><div><span style=3D"font-family:arial,h=
elvetica,sans-serif"><b>Note 2:</b> advantage over some other proposals is =
in the uniform type <span style=3D"font-family:monospace,monospace">array_v=
iew<T,Rank></span> that doesn't depend on the "continuousnes=
s" (unlike n4177 where strided view is a separate type </span><span st=
yle=3D"font-family:arial,helvetica,sans-serif"><code>strided_array_view</co=
de>). <br>For those who need to know if the view is contiguous (for example=
, to do a bulk <span style=3D"font-family:monospace,monospace">memcpy</span=
> instead of element-wise copying) there is a member function=C2=A0 <span s=
tyle=3D"font-family:monospace,monospace">bool continuous() const</span> pro=
vided that just checks if <span style=3D"font-family:monospace,monospace">s=
izeof(T)=3D=3Dbyte_stride</span>.<br></span><span style=3D"font-family:aria=
l,helvetica,sans-serif"><br></span></div><div><span style=3D"font-family:ar=
ial,helvetica,sans-serif"><b>Note 3:</b> array_view supports default constr=
uction and assignment (this is necessary for the cases when we have a view =
in the host program, then we load a plugin, attach to its memory, and initi=
alized our array_view to look at the plugin's memory, and then we can u=
nload the plugin and load another, with a different derived type, and reini=
tialized our array_view again).<br><br></span></div><div><span style=3D"fon=
t-family:arial,helvetica,sans-serif"><br></span></div><div><span style=3D"f=
ont-family:arial,helvetica,sans-serif">Comments?<br>If there is </span><spa=
n style=3D"font-family:arial,helvetica,sans-serif"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:monospace,monospace"></s=
pan></span></span>an agreement that it would be good to have (from my exper=
ience, it is) I'll write a formal proposal.<br><br></div></div></blockq=
uote><div><br></div><div><span style=3D"font-size:12.800000190734863px;font=
-family:arial,helvetica,sans-serif">A byte-strided=C2=A0</span><span style=
=3D"font-size:12.800000190734863px;font-family:monospace,monospace">array_v=
iew would lose many of the advantages of memory contiguity. I'd be incl=
ined to use a struct of array_views rather than a strided array view of str=
ucts.</span><br></div><div>=C2=A0</div><div><div><div style=3D"margin-left:=
40px"><span style=3D"font-family:monospace,monospace">struct C_view {<br></=
span></div><div style=3D"margin-left:40px"><span style=3D"font-family:monos=
pace,monospace">=C2=A0 array_view<int> as;</span><br><span style=3D"f=
ont-family:monospace,monospace"></span></div></div><div style=3D"margin-lef=
t:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 array_view&l=
t;B> bs;</span></div><div style=3D"margin-left:40px"><span style=3D"font=
-family:monospace,monospace">};</span></div></div><div><br></div><div>I thi=
nk there are already some proposals in flight to convert vectors of structs=
into structs of vectors.</div><div><br></div><div>Regards,</div><div><br><=
/div><div>Jon</div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>=
</div><div>Thanks everyone,<br></div><div>Yours sincerely,<br></div><div>Ma=
xim Yanchenko<span class=3D"gmail-HOEnZb"><font color=3D"#888888"><br></fon=
t></span></div><span class=3D"gmail-HOEnZb"><font color=3D"#888888"><div><s=
pan style=3D"font-family:monospace,monospace"><br></span></div></font></spa=
n></div><span class=3D"gmail-HOEnZb"><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3=
Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter" target=3D"_blank">https://groups.google.com/a/<wbr>isocpp.org/d/msgi=
d/std-<wbr>proposals/CA%2B6mTDf_%<wbr>2BdxPnZBjLUKgWnEG9N6X_Q%<wbr>3Dg5Umvm=
d78GXfDG2K2xw%40mail.<wbr>gmail.com</a>.<br>
</font></span></blockquote></div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPC=
zKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%=
2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com</a>.<br />
--001a11416e8c6f1c80054bb988db--
.
Author: =?UTF-8?Q?Micha=C5=82_Dominiak?= <griwes@griwes.info>
Date: Mon, 27 Mar 2017 17:29:42 +0000
Raw View
--94eb2c12f94cece42c054bb9b0d1
Content-Type: text/plain; charset=UTF-8
And how exactly do you initialize those array_views inside?
You do realize that the vector of structs case is vastly different, because
vectors are owning and need to allocate memory, while this allocates no
memory at all, right?
(These are the effects of religiously following a paradigm and trying to
use it as a hammer.)
On Mon, Mar 27, 2017 at 7:18 PM Jonathan Coe <jonathanbcoe@gmail.com> wrote:
> On 27 March 2017 at 18:10, Maxim Yanchenko <maxim.yanchenko@gmail.com>
> wrote:
>
> Good day to everyone,
>
> I checked the existing proposals regarding array_view (including the
> multi-dimensional and strided ones) and I found none that would support
> byte stride (please correct me if I missed one, apologies in advance).
> I have my own custom array view written long time ago which I use a lot
> and found it extremely convenient, and it differs from the proposed
> array_view by having an additional runtime parameter byte_stride
> (defaulted to sizeof(T) to have usual array_view by default).
> The byte_stride is not part of the type, so the type is still the same array_view<class
> T, int Rank=1> and you can use it for both contiguous arrays and byte-strided
> arrays.
>
> So the constructor looks like this (for 1D array view):
> array_view( T* ptr, size_t size, size_t byte_stride = sizeof(T) );
>
> *Motivation*
> In scientific/financial calculations one often has arrays of sets of
> parameters, i.e. arrays of structs:
> struct BasicData {
> int data1;
> int data2;
> };
> BasicData barr[50];
> It's also not unusual to have extended versions of algorithms that use
> additional parameters on top of the generic ones (or save additional data
> on top of the common one).
> The natural way of dealing with this is just inheriting from the basic
> struct and make an array of the derived struct:
> struct ExtendedData : BasicData {
> int data3;
> };
> ExtendedData earr[50];
> this way you can access common and extended data the same way without
> changing your code (and you can freely move parameters from derived struct
> to the base and back, without affecting the specialized code that uses
> them):
> earr.data1[i] = earr.data2[i] * earr.data3[i];
>
> The problem here is that now even the code that doesn't need extended data
> (like ones gathering common statistics or statuses) and would happily run
> on just basic data (and therefore could have been factored out to the
> common unspecialized codebase)
> void common_processing(array_view<BasicData>);
> Such a function can't run because there is no array of basic params
> anymore, they are hidden inside the bigger extended params struct, and
> there is currently no way to get an array_view<BasicData> out of earr.
> Strided array_view won't help because sizeof(BasicData) is 2*sizeof(int),
> while sizeof(ExtendedData) is 3*sizeof(int) - so strides of sizeof(
> BasicData) won't work.
>
> Also, there can be a plugin-like architecture of the program so the host
> wouldn't even know the type ExtendedData that exists only in the plugin
> but still could access BasicData owned by the plugin if there was a way
> to construct
> array_view<BasicData>.
>
> All the above is easily achievable with a byte-strided array_view.
>
>
> Another example: think of BasicData as RGB and ExtendedData as RGBA/ARGB:
> you could have an array_view<RGB> over an RGBA file and an RGB file and
> even an ARGB file, agnostically - they will only differ in their
> byte_stride value.
>
>
>
> Here are the use cases (1D, for simplicity):
>
> *1) Use as a normal array_view:*
> struct B {
> int x,y;
> };
> B *pb = new B[50];
> array_view<B> av( pb, 50 ); // byte_stride is defaulted to sizeof(B)
>
> *2) view of an array of a derived class D as an array of base class B:*
> struct B {
> int x,y;
> };
> struct D: B {
> int a;
> };
> D *pd = new D[50];
> array_view<B> av_b( pd, 50, sizeof(D) );
>
> (pd automatically converted to B*, sizeof(B) == 2*sizeof(int), sizeof(D)
> == 3*sizeof(int) so usual integer stride won't work here because sizeof(D)
> is not a multiple of sizeof(B))
>
> to avoid mistakes, an obvious helper function array_view_by_base() is
> provided (it also checks static_assert(std::is_base_of_v<B,D>)):
> array_view<B> av_b = array_view_by_base<B>( pd, 50 );
>
> *3) Member view ("array" of field b):*
> struct B {
> int x,y;
> };
> struct C {
> int a;
> B b;
> };
> C *pc = new C[50];
> array_view<B> av_b( &pc[0].b, 50, sizeof(C) );
> array_view<int> av_y( &pc[0].b.y, 50, sizeof(C) );
>
> Again, to avoid mistakes, a helper function array_view_by_member() is
> provided:
> array_view<B> av_b = array_view_by_member( pc, &C::b, 50 ); // both D
> and B are deduced from the arguments
>
> Unfortunately, there is currently no way in C++ to have a nested
> pointer-to-member so it's impossible to write something like &C::b::y.
> This can be emulated, to some extent, by providing a tuple like (&C::b,
> &B::y) but it's not much more readable than the unsafe version. So the
> safe version for av_y would be:
> array_view<int> av_y = array_view_by_member( pc, std::make_tuple(&C::b,
> &B::y), 50 ); // both D and int are deduced from the arguments
>
> *4) Strided views for all the cases above*:
> Just call the constructor with stride*sizeof(D) instead of just sizeof(D)
>
>
> *Note 1:* when the argument p above is not a plain pointer but a
> container that knows its size (via std::size - think of std::vector,
> std::array, or even another array_view) then you don't need to provide the
> size manually:
> std::vector<B> vb;
> array_view<B> av_b( vb );
> std::vector<D> vd;
> array_view<B> av_b = array_view_by_base<B>( vd );
> std::vector<C> vc;
> array_view<B> av_b = array_view_by_member( vc, &C::b );
>
> *Note 2:* advantage over some other proposals is in the uniform type
> array_view<T,Rank> that doesn't depend on the "continuousness" (unlike
> n4177 where strided view is a separate type strided_array_view).
> For those who need to know if the view is contiguous (for example, to do a
> bulk memcpy instead of element-wise copying) there is a member function bool
> continuous() const provided that just checks if sizeof(T)==byte_stride.
>
> *Note 3:* array_view supports default construction and assignment (this
> is necessary for the cases when we have a view in the host program, then we
> load a plugin, attach to its memory, and initialized our array_view to look
> at the plugin's memory, and then we can unload the plugin and load another,
> with a different derived type, and reinitialized our array_view again).
>
>
> Comments?
> If there is an agreement that it would be good to have (from my
> experience, it is) I'll write a formal proposal.
>
>
> A byte-strided array_view would lose many of the advantages of memory
> contiguity. I'd be inclined to use a struct of array_views rather than a
> strided array view of structs.
>
> struct C_view {
> array_view<int> as;
> array_view<B> bs;
> };
>
> I think there are already some proposals in flight to convert vectors of
> structs into structs of vectors.
>
> Regards,
>
> Jon
>
> Thanks everyone,
> Yours sincerely,
> Maxim Yanchenko
>
> --
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
> --
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit
> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPCFJdRZXSCDa94NdB_YRn-3DSWaVGWMvFM2sTz7CYovjqqy6w%40mail.gmail.com.
--94eb2c12f94cece42c054bb9b0d1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>And how exactly do you initialize those array_views i=
nside?</div><div><br></div><div>You do realize that the vector of structs c=
ase is vastly different, because vectors are owning and need to allocate me=
mory, while this allocates no memory at all, right?</div><div><br></div><di=
v>(These are the effects of religiously following a paradigm and trying to =
use it as a hammer.)</div></div><br><div class=3D"gmail_quote"><div dir=3D"=
ltr">On Mon, Mar 27, 2017 at 7:18 PM Jonathan Coe <<a href=3D"mailto:jon=
athanbcoe@gmail.com">jonathanbcoe@gmail.com</a>> wrote:<br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr" class=3D"gmail_msg"><div class=3D"=
gmail_extra gmail_msg"><div class=3D"gmail_quote gmail_msg">On 27 March 201=
7 at 18:10, Maxim Yanchenko <span dir=3D"ltr" class=3D"gmail_msg"><<a hr=
ef=3D"mailto:maxim.yanchenko@gmail.com" class=3D"gmail_msg" target=3D"_blan=
k">maxim.yanchenko@gmail.com</a>></span> wrote:<br class=3D"gmail_msg"><=
blockquote class=3D"gmail_quote gmail_msg" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr" class=3D"gmail_msg"><div class=
=3D"gmail_msg"><div class=3D"gmail_msg"><div class=3D"gmail_msg"><div class=
=3D"gmail_msg"><div class=3D"gmail_msg"><div class=3D"gmail_msg">Good day t=
o everyone,<br class=3D"gmail_msg"><br class=3D"gmail_msg">I checked the ex=
isting proposals regarding <span style=3D"font-family:monospace,monospace" =
class=3D"gmail_msg">array_view</span> (including the multi-dimensional and =
strided ones) and I found none that would support byte stride (please corre=
ct me if I missed one, apologies in advance).<br class=3D"gmail_msg"></div>=
I have my own custom array view written long time ago which I use a lot and=
found it extremely convenient, and it differs from the proposed <span styl=
e=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view</span>=
by having an additional runtime parameter <span style=3D"font-family:monos=
pace,monospace" class=3D"gmail_msg">byte_stride</span> (defaulted to <span =
style=3D"font-family:monospace,monospace" class=3D"gmail_msg">sizeof(T)</sp=
an> to have usual <span style=3D"font-family:monospace,monospace" class=3D"=
gmail_msg">array_view</span> by default).<br class=3D"gmail_msg"></div>The =
<span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">byte_st=
ride</span> is not part of the type, so the type is still the same <span st=
yle=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view<c=
lass T, int Rank=3D1></span><span style=3D"font-family:arial,helvetica,s=
ans-serif" class=3D"gmail_msg"> and</span> you can use it for both contiguo=
us arrays and <span style=3D"font-family:arial,helvetica,sans-serif" class=
=3D"gmail_msg">byte-strided </span>arrays.<br class=3D"gmail_msg"><br class=
=3D"gmail_msg"></div><div class=3D"gmail_msg">So the constructor looks like=
this (for 1D array view): <br class=3D"gmail_msg"></div><div class=3D"gmai=
l_msg"><div style=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"f=
ont-family:monospace,monospace" class=3D"gmail_msg">array_view( T* ptr, siz=
e_t size, size_t byte_stride =3D sizeof(T) );</span><br class=3D"gmail_msg"=
></div><br class=3D"gmail_msg"></div><div class=3D"gmail_msg"><b class=3D"g=
mail_msg">Motivation</b><br class=3D"gmail_msg"></div><div class=3D"gmail_m=
sg">In scientific/financial calculations one often has arrays of sets of pa=
rameters, i.e. arrays of structs:<br class=3D"gmail_msg"></div><div style=
=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monosp=
ace,monospace" class=3D"gmail_msg">struct BasicData {<br class=3D"gmail_msg=
"></span></div><div style=3D"margin-left:40px" class=3D"gmail_msg"><span st=
yle=3D"font-family:monospace,monospace" class=3D"gmail_msg">=C2=A0 int data=
1;<br class=3D"gmail_msg"></span></div><div style=3D"margin-left:40px" clas=
s=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gm=
ail_msg">=C2=A0 int data2;<br class=3D"gmail_msg"></span></div><div style=
=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monosp=
ace,monospace" class=3D"gmail_msg">};<br class=3D"gmail_msg"></span><span s=
tyle=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=3D=
"font-family:monospace,monospace" class=3D"gmail_msg">BasicData </span>barr=
[50]; </span></div><div class=3D"gmail_msg">It's also not unusual to ha=
ve extended versions of algorithms that use additional parameters on top of=
the generic ones (or save additional data on top of the common one).<br cl=
ass=3D"gmail_msg"></div><div class=3D"gmail_msg">The natural way of dealing=
with this is just inheriting from the basic struct and make an array of th=
e derived struct:<br class=3D"gmail_msg"></div><div style=3D"margin-left:40=
px" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg">struct </span><span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg">ExtendedData </span><span style=3D"font-family:arial,helve=
tica,sans-serif" class=3D"gmail_msg"></span>: </span><span style=3D"font-fa=
mily:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:mo=
nospace,monospace" class=3D"gmail_msg">BasicData </span>{<br class=3D"gmail=
_msg"></span></div><div style=3D"margin-left:40px" class=3D"gmail_msg"><spa=
n style=3D"font-family:monospace,monospace" class=3D"gmail_msg">=C2=A0 int =
data3;<br class=3D"gmail_msg"></span></div><div class=3D"gmail_msg"><div st=
yle=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:mon=
ospace,monospace" class=3D"gmail_msg">};<br class=3D"gmail_msg"></span><spa=
n style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=3D"fon=
t-family:monospace,monospace" class=3D"gmail_msg">ExtendedData e</span></sp=
an>arr[50];</span><br class=3D"gmail_msg"></div> this way you can access co=
mmon and extended data the same way=20
without changing your code (and you can freely move parameters from=20
derived struct to the base and back, without affecting the specialized=20
code that uses them):<br class=3D"gmail_msg"></div><div style=3D"margin-lef=
t:40px" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace"=
class=3D"gmail_msg">earr.data1[i] =3D earr.data2[i] * earr.data3[i];<br cl=
ass=3D"gmail_msg"><br class=3D"gmail_msg"></span></div><div class=3D"gmail_=
msg">The problem here is that now even the code that doesn't need exten=
ded data (like ones gathering common statistics or statuses) and would happ=
ily run on just basic data (and therefore could have been factored out to t=
he common unspecialized codebase)<br class=3D"gmail_msg"><div style=3D"marg=
in-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monospace,mono=
space" class=3D"gmail_msg">void common_processing(array_view<</span><spa=
n style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">BasicData</span>&g=
t;);</span><br class=3D"gmail_msg"></div>Such a function can't run beca=
use there is no array of basic params anymore, they are hidden inside the b=
igger extended params struct, and there is currently no way to get an <span=
style=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view&l=
t;BasicData></span> out of <span style=3D"font-family:monospace,monospac=
e" class=3D"gmail_msg">earr</span>.<br class=3D"gmail_msg"></div><div class=
=3D"gmail_msg">Strided array_view won't help because <span style=3D"fon=
t-family:monospace,monospace" class=3D"gmail_msg">sizeof(BasicData) </span>=
<span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_msg">=
is </span><span style=3D"font-family:monospace,monospace" class=3D"gmail_ms=
g">2*sizeof(int), while sizeof(</span><span style=3D"font-family:monospace,=
monospace" class=3D"gmail_msg">ExtendedData</span><span style=3D"font-famil=
y:arial,helvetica,sans-serif" class=3D"gmail_msg"></span><span style=3D"fon=
t-family:monospace,monospace" class=3D"gmail_msg">) </span><span style=3D"f=
ont-family:arial,helvetica,sans-serif" class=3D"gmail_msg">is </span><span =
style=3D"font-family:monospace,monospace" class=3D"gmail_msg">3*sizeof(int)=
</span><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmai=
l_msg"> - so strides of </span><span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg">sizeof(</span><span style=3D"font-family:monospace,=
monospace" class=3D"gmail_msg">BasicData</span><span style=3D"font-family:m=
onospace,monospace" class=3D"gmail_msg">)</span><span style=3D"font-family:=
arial,helvetica,sans-serif" class=3D"gmail_msg"> won't work.</span><spa=
n style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><br class=
=3D"gmail_msg"></span></div><div class=3D"gmail_msg"><br class=3D"gmail_msg=
"></div><div class=3D"gmail_msg">Also, there can be a plugin-like architect=
ure of the program so the host wouldn't even know the type <span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">ExtendedData </spa=
n><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_msg=
"></span><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gm=
ail_msg">that exists only in the plugin but still could access</span><span =
style=3D"font-family:monospace,monospace" class=3D"gmail_msg"> </span><span=
style=3D"font-family:monospace,monospace" class=3D"gmail_msg">BasicData </=
span><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_=
msg">owned by the plugin if there was a way to construct </span><br class=
=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gma=
il_msg">array_view<</span><span style=3D"font-family:monospace,monospace=
" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=
=3D"gmail_msg">BasicData</span>>.</span></div><div class=3D"gmail_msg"><=
br class=3D"gmail_msg">All the above is easily achievable with <span style=
=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_msg">a byte-stri=
ded </span><span style=3D"font-family:monospace,monospace" class=3D"gmail_m=
sg">array_view</span>.<br class=3D"gmail_msg"><br class=3D"gmail_msg"><br c=
lass=3D"gmail_msg"></div><div class=3D"gmail_msg">Another example: think of=
<span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">BasicD=
ata </span>as<span style=3D"font-family:monospace,monospace" class=3D"gmail=
_msg"> RGB </span>and <span style=3D"font-family:monospace,monospace" class=
=3D"gmail_msg">ExtendedData </span><span style=3D"font-family:arial,helveti=
ca,sans-serif" class=3D"gmail_msg">as<span style=3D"font-family:monospace,m=
onospace" class=3D"gmail_msg"> </span></span><span style=3D"font-family:mon=
ospace,monospace" class=3D"gmail_msg">RGBA/ARGB:</span> you could have an <=
span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_vi=
ew<RGB></span> over an RGBA file and an RGB file and even an ARGB fil=
e, agnostically - they will only differ in their <span style=3D"font-family=
:monospace,monospace" class=3D"gmail_msg">byte_stride</span> value.<br clas=
s=3D"gmail_msg"><br class=3D"gmail_msg"><br class=3D"gmail_msg"></div><div =
class=3D"gmail_msg"><br class=3D"gmail_msg"></div>Here are the use cases (1=
D, for simplicity):<br class=3D"gmail_msg"><br class=3D"gmail_msg"></div><d=
iv class=3D"gmail_msg"><b class=3D"gmail_msg">1) Use as a normal <span styl=
e=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view</span>=
:</b><br class=3D"gmail_msg"></div><div style=3D"margin-left:40px" class=3D=
"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_=
msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">st=
ruct B {<br class=3D"gmail_msg"></span><span style=3D"font-family:monospace=
,monospace" class=3D"gmail_msg">=C2=A0 int x,y;<br class=3D"gmail_msg"></sp=
an><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">};<b=
r class=3D"gmail_msg"></span></span><span style=3D"font-family:monospace,mo=
nospace" class=3D"gmail_msg">B *pb =3D new B[50];</span></div><div class=3D=
"gmail_msg"><div style=3D"margin-left:40px" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view<B>=
; av( pb, 50 ); // byte_stride</span><span style=3D"font-family:arial,helve=
tica,sans-serif" class=3D"gmail_msg"> is defaulted to</span><span style=3D"=
font-family:monospace,monospace" class=3D"gmail_msg"> sizeof(B)</span><br c=
lass=3D"gmail_msg"></div><div style=3D"margin-left:40px" class=3D"gmail_msg=
"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"></spa=
n></div><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"=
><br class=3D"gmail_msg"></span></div><b class=3D"gmail_msg">2) view of an =
array of a derived class D as an array of base class B:</b><br class=3D"gma=
il_msg"></div><span style=3D"font-family:monospace,monospace" class=3D"gmai=
l_msg"></span></div><div style=3D"margin-left:40px" class=3D"gmail_msg"><sp=
an style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span styl=
e=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=3D"fo=
nt-family:monospace,monospace" class=3D"gmail_msg">struct B {<br class=3D"g=
mail_msg"></span><span style=3D"font-family:monospace,monospace" class=3D"g=
mail_msg">=C2=A0 int x,y;<br class=3D"gmail_msg"></span><span style=3D"font=
-family:monospace,monospace" class=3D"gmail_msg">};<br class=3D"gmail_msg">=
</span></span><span style=3D"font-family:monospace,monospace" class=3D"gmai=
l_msg"></span>struct D: B {<br class=3D"gmail_msg"></span></div><div style=
=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monosp=
ace,monospace" class=3D"gmail_msg">=C2=A0 int a;<br class=3D"gmail_msg">};<=
br class=3D"gmail_msg"></span></div><div style=3D"margin-left:40px" class=
=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gma=
il_msg">D *pd =3D new D[50];<br class=3D"gmail_msg"></span></div><div class=
=3D"gmail_msg"><div style=3D"margin-left:40px" class=3D"gmail_msg"><span st=
yle=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_view<B=
> av_b( pd, 50, sizeof(D) );<br class=3D"gmail_msg"><br class=3D"gmail_m=
sg"></span><span style=3D"font-family:monospace,monospace" class=3D"gmail_m=
sg"></span></div><span style=3D"font-family:arial,helvetica,sans-serif" cla=
ss=3D"gmail_msg">(</span><span style=3D"font-family:monospace,monospace" cl=
ass=3D"gmail_msg">pd </span><span style=3D"font-family:arial,helvetica,sans=
-serif" class=3D"gmail_msg">automatically converted to </span><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">B*, sizeof(B) =3D=
=3D 2*sizeof(int), sizeof(D) =3D=3D 3*sizeof(int)</span><span style=3D"font=
-family:arial,helvetica,sans-serif" class=3D"gmail_msg"> so usual integer s=
tride won't work here because <span style=3D"font-family:monospace,mono=
space" class=3D"gmail_msg">sizeof(D)</span> is not a multiple of <span styl=
e=3D"font-family:monospace,monospace" class=3D"gmail_msg">sizeof(B)</span>)=
</span><br class=3D"gmail_msg"><br class=3D"gmail_msg"></div><div class=3D"=
gmail_msg">to avoid mistakes, an obvious helper function <span style=3D"fon=
t-family:monospace,monospace" class=3D"gmail_msg">array_view_by_base()</spa=
n> is provided (it also checks <span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg">static_assert(std::is_base_of_v<B,D>)</span>)=
:<br class=3D"gmail_msg"></div><div style=3D"margin-left:40px" class=3D"gma=
il_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"=
>array_view<B> av_b =3D array_view_by_base<B>( pd, 50 );</span>=
</div><div class=3D"gmail_msg"><br class=3D"gmail_msg"></div><div class=3D"=
gmail_msg"><b class=3D"gmail_msg">3) Member view ("array" of fiel=
d b):</b><br class=3D"gmail_msg"><div style=3D"margin-left:40px" class=3D"g=
mail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_ms=
g"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><spa=
n style=3D"font-family:monospace,monospace" class=3D"gmail_msg">struct B {<=
br class=3D"gmail_msg"></span><span style=3D"font-family:monospace,monospac=
e" class=3D"gmail_msg">=C2=A0 int x,y;<br class=3D"gmail_msg"></span><span =
style=3D"font-family:monospace,monospace" class=3D"gmail_msg">};<br class=
=3D"gmail_msg"></span></span><span style=3D"font-family:monospace,monospace=
" class=3D"gmail_msg"></span>struct C {<br class=3D"gmail_msg"></span></div=
><div style=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-fa=
mily:monospace,monospace" class=3D"gmail_msg">=C2=A0 int a;</span><br class=
=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gma=
il_msg"></span></div></div><div style=3D"margin-left:40px" class=3D"gmail_m=
sg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">=C2=
=A0 B b;<br class=3D"gmail_msg"></span></div><div style=3D"margin-left:40px=
" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=
=3D"gmail_msg">};</span><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg"><br class=3D"gmail_msg"></span><span style=3D"font-family:=
monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospa=
ce,monospace" class=3D"gmail_msg">C *pc =3D new C[50];<br class=3D"gmail_ms=
g"></span></span></div><div style=3D"margin-left:40px" class=3D"gmail_msg">=
<span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">array_v=
iew<B>=C2=A0=C2=A0 av_b( </span><span style=3D"font-family:monospace,=
monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg">&pc[0].b,=C2=A0=C2=A0 50, sizeof(C) </span>);<b=
r class=3D"gmail_msg"></span></div><div style=3D"margin-left:40px" class=3D=
"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_=
msg">array_view<int> av_y( </span><span style=3D"font-family:monospac=
e,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,monos=
pace" class=3D"gmail_msg">&pc[0].b.y, 50, sizeof(C) </span>);<br class=
=3D"gmail_msg"></span></div><span style=3D"font-family:monospace,monospace"=
class=3D"gmail_msg"></span><span style=3D"font-family:monospace,monospace"=
class=3D"gmail_msg"><font face=3D"arial,helvetica,sans-serif" class=3D"gma=
il_msg"><br class=3D"gmail_msg">Again, to avoid mistakes, a helper function=
</font>array_view_by_member()</span><span style=3D"font-family:arial,helve=
tica,sans-serif" class=3D"gmail_msg"> is provided</span>:<br class=3D"gmail=
_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><=
/span><div style=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"fo=
nt-family:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-fami=
ly:monospace,monospace" class=3D"gmail_msg">array_view<B>=C2=A0=C2=A0=
av_b =3D array_view_by_member( pc, &C::b, 50 );</span></span> // both =
D and B are deduced from the arguments<br class=3D"gmail_msg"><br class=3D"=
gmail_msg"></div><div class=3D"gmail_msg">Unfortunately, there is currently=
no way in C++ to have a nested pointer-to-member so it's impossible to=
write something like <span style=3D"font-family:monospace,monospace" class=
=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gma=
il_msg">&C::b::y</span></span><span style=3D"font-family:arial,helvetic=
a,sans-serif" class=3D"gmail_msg">. This can be emulated, to some extent, b=
y providing a tuple like <span style=3D"font-family:monospace,monospace" cl=
ass=3D"gmail_msg">(&C::b, &B::y)</span> but it's not much more =
readable than the unsafe version. So the safe version for <span style=3D"fo=
nt-family:'times new roman',serif" class=3D"gmail_msg">av_y</span> =
would be</span><span style=3D"font-family:'times new roman',serif" =
class=3D"gmail_msg">:</span><span style=3D"font-family:monospace,monospace"=
class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=
=3D"gmail_msg"><br class=3D"gmail_msg"></span></span><div style=3D"margin-l=
eft:40px" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospac=
e" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" clas=
s=3D"gmail_msg">array_view<int> av_y =3D array_view_by_member( pc, st=
d::make_tuple(&C::b,</span></span><span style=3D"font-family:monospace,=
monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg"><span style=3D"font-family:arial,helvetica,sans-ser=
if" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg"> &B::y)</span></span>, 50 );</span></span> // both D a=
nd int are deduced from the arguments</div></div><div class=3D"gmail_msg"><=
br class=3D"gmail_msg"></div><div class=3D"gmail_msg"><b class=3D"gmail_msg=
">4) Strided views for all the cases above</b>:<br class=3D"gmail_msg"></di=
v><div class=3D"gmail_msg">Just call the constructor with stride*sizeof(D) =
instead of just sizeof(D)<br class=3D"gmail_msg"></div><div class=3D"gmail_=
msg"><br class=3D"gmail_msg"><br class=3D"gmail_msg"></div><div class=3D"gm=
ail_msg"><b class=3D"gmail_msg">Note 1:</b> when the argument p above is no=
t a plain pointer but a container that knows its size (via std::size - thin=
k of std::vector, std::array, or even another array_view) then you don'=
t need to provide the size manually:<br class=3D"gmail_msg"><div style=3D"m=
argin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monospace,m=
onospace" class=3D"gmail_msg">std::vector<B> vb;</span><br class=3D"g=
mail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_ms=
g">array_view<B> av_b( vb );</span><br class=3D"gmail_msg"><span styl=
e=3D"font-family:monospace,monospace" class=3D"gmail_msg">std::vector<D&=
gt; vd;</span><br class=3D"gmail_msg"><span style=3D"font-family:monospace,=
monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospa=
ce" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" class=3D"g=
mail_msg">array_view<B> av_b =3D </span>array_view_by_base<B>( =
vd );</span></span></span><br class=3D"gmail_msg"><span style=3D"font-famil=
y:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monos=
pace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,mo=
nospace" class=3D"gmail_msg"></span></span></span><span style=3D"font-famil=
y:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monos=
pace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,mo=
nospace" class=3D"gmail_msg">std::vector<C> vc;</span><br class=3D"gm=
ail_msg"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg=
"><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span=
style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg"></span></span></sp=
an></span>array_view<B> av_b =3D </span></span><span style=3D"font-fa=
mily:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:mo=
nospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace=
,monospace" class=3D"gmail_msg"><span style=3D"font-family:monospace,monosp=
ace" class=3D"gmail_msg">array_view_by_member</span></span></span>( vc</spa=
n><span style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span=
style=3D"font-family:monospace,monospace" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">, &C::b</span>=
</span> );</span><br class=3D"gmail_msg"></div><div style=3D"margin-left:40=
px" class=3D"gmail_msg"><span style=3D"font-family:monospace,monospace" cla=
ss=3D"gmail_msg"></span></div><span style=3D"font-family:monospace,monospac=
e" class=3D"gmail_msg"><br class=3D"gmail_msg"></span></div><div class=3D"g=
mail_msg"><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"g=
mail_msg"><b class=3D"gmail_msg">Note 2:</b> advantage over some other prop=
osals is in the uniform type <span style=3D"font-family:monospace,monospace=
" class=3D"gmail_msg">array_view<T,Rank></span> that doesn't depe=
nd on the "continuousness" (unlike n4177 where strided view is a =
separate type </span><span style=3D"font-family:arial,helvetica,sans-serif"=
class=3D"gmail_msg"><code class=3D"gmail_msg">strided_array_view</code>). =
<br class=3D"gmail_msg">For those who need to know if the view is contiguou=
s (for example, to do a bulk <span style=3D"font-family:monospace,monospace=
" class=3D"gmail_msg">memcpy</span> instead of element-wise copying) there =
is a member function=C2=A0 <span style=3D"font-family:monospace,monospace" =
class=3D"gmail_msg">bool continuous() const</span> provided that just check=
s if <span style=3D"font-family:monospace,monospace" class=3D"gmail_msg">si=
zeof(T)=3D=3Dbyte_stride</span>.<br class=3D"gmail_msg"></span><span style=
=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_msg"><br class=
=3D"gmail_msg"></span></div><div class=3D"gmail_msg"><span style=3D"font-fa=
mily:arial,helvetica,sans-serif" class=3D"gmail_msg"><b class=3D"gmail_msg"=
>Note 3:</b> array_view supports default construction and assignment (this =
is necessary for the cases when we have a view in the host program, then we=
load a plugin, attach to its memory, and initialized our array_view to loo=
k at the plugin's memory, and then we can unload the plugin and load an=
other, with a different derived type, and reinitialized our array_view agai=
n).<br class=3D"gmail_msg"><br class=3D"gmail_msg"></span></div><div class=
=3D"gmail_msg"><span style=3D"font-family:arial,helvetica,sans-serif" class=
=3D"gmail_msg"><br class=3D"gmail_msg"></span></div><div class=3D"gmail_msg=
"><span style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_msg=
">Comments?<br class=3D"gmail_msg">If there is </span><span style=3D"font-f=
amily:arial,helvetica,sans-serif" class=3D"gmail_msg"><span style=3D"font-f=
amily:monospace,monospace" class=3D"gmail_msg"><span style=3D"font-family:m=
onospace,monospace" class=3D"gmail_msg"></span></span></span>an agreement t=
hat it would be good to have (from my experience, it is) I'll write a f=
ormal proposal.<br class=3D"gmail_msg"><br class=3D"gmail_msg"></div></div>=
</blockquote><div class=3D"gmail_msg"><br class=3D"gmail_msg"></div></div><=
/div></div><div dir=3D"ltr" class=3D"gmail_msg"><div class=3D"gmail_extra g=
mail_msg"><div class=3D"gmail_quote gmail_msg"><div class=3D"gmail_msg"><sp=
an style=3D"font-size:12.800000190734863px;font-family:arial,helvetica,sans=
-serif" class=3D"gmail_msg">A byte-strided=C2=A0</span><span style=3D"font-=
size:12.800000190734863px;font-family:monospace,monospace" class=3D"gmail_m=
sg">array_view would lose many of the advantages of memory contiguity. I=
9;d be inclined to use a struct of array_views rather than a strided array =
view of structs.</span><br class=3D"gmail_msg"></div><div class=3D"gmail_ms=
g">=C2=A0</div><div class=3D"gmail_msg"><div class=3D"gmail_msg"><div style=
=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monosp=
ace,monospace" class=3D"gmail_msg">struct C_view {<br class=3D"gmail_msg"><=
/span></div><div style=3D"margin-left:40px" class=3D"gmail_msg"><span style=
=3D"font-family:monospace,monospace" class=3D"gmail_msg">=C2=A0 array_view&=
lt;int> as;</span><br class=3D"gmail_msg"><span style=3D"font-family:mon=
ospace,monospace" class=3D"gmail_msg"></span></div></div><div style=3D"marg=
in-left:40px" class=3D"gmail_msg"><span style=3D"font-family:monospace,mono=
space" class=3D"gmail_msg">=C2=A0 array_view<B> bs;</span></div><div =
style=3D"margin-left:40px" class=3D"gmail_msg"><span style=3D"font-family:m=
onospace,monospace" class=3D"gmail_msg">};</span></div></div><div class=3D"=
gmail_msg"><br class=3D"gmail_msg"></div><div class=3D"gmail_msg">I think t=
here are already some proposals in flight to convert vectors of structs int=
o structs of vectors.</div><div class=3D"gmail_msg"><br class=3D"gmail_msg"=
></div><div class=3D"gmail_msg">Regards,</div><div class=3D"gmail_msg"><br =
class=3D"gmail_msg"></div><div class=3D"gmail_msg">Jon</div></div></div></d=
iv><div dir=3D"ltr" class=3D"gmail_msg"><div class=3D"gmail_extra gmail_msg=
"><div class=3D"gmail_quote gmail_msg"><div class=3D"gmail_msg"><br class=
=3D"gmail_msg"></div><blockquote class=3D"gmail_quote gmail_msg" style=3D"m=
argin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204=
,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr" class=3D"g=
mail_msg"><div class=3D"gmail_msg"></div><div class=3D"gmail_msg">Thanks ev=
eryone,<br class=3D"gmail_msg"></div><div class=3D"gmail_msg">Yours sincere=
ly,<br class=3D"gmail_msg"></div><div class=3D"gmail_msg">Maxim Yanchenko<s=
pan class=3D"m_213307598196650340gmail-HOEnZb gmail_msg"><font color=3D"#88=
8888" class=3D"gmail_msg"><br class=3D"gmail_msg"></font></span></div><span=
class=3D"m_213307598196650340gmail-HOEnZb gmail_msg"><font color=3D"#88888=
8" class=3D"gmail_msg"><div class=3D"gmail_msg"><span style=3D"font-family:=
monospace,monospace" class=3D"gmail_msg"><br class=3D"gmail_msg"></span></d=
iv></font></span></div><span class=3D"m_213307598196650340gmail-HOEnZb gmai=
l_msg"><font color=3D"#888888" class=3D"gmail_msg">
<p class=3D"gmail_msg"></p>
-- <br class=3D"gmail_msg">
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br class=3D"gmail_msg=
">
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" class=3D"gm=
ail_msg" target=3D"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br cla=
ss=3D"gmail_msg">
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" class=3D"gmail_msg" target=3D"_blank">std-proposals@isocpp.org</a>.<b=
r class=3D"gmail_msg">
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3=
Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter" class=3D"gmail_msg" target=3D"_blank">https://groups.google.com/a/is=
ocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvm=
d78GXfDG2K2xw%40mail.gmail.com</a>.<br class=3D"gmail_msg">
</font></span></blockquote></div></div></div>
<p class=3D"gmail_msg"></p>
-- <br class=3D"gmail_msg">
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br class=3D"gmail_msg=
">
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" class=3D"gm=
ail_msg" target=3D"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br cla=
ss=3D"gmail_msg">
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" class=3D"gmail_msg" target=3D"_blank">std-proposals@isocpp.org</a>.<b=
r class=3D"gmail_msg">
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPC=
zKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r" class=3D"gmail_msg" target=3D"_blank">https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj=
-Hq7w%40mail.gmail.com</a>.<br class=3D"gmail_msg">
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAPCFJdRZXSCDa94NdB_YRn-3DSWaVGWMvFM2=
sTz7CYovjqqy6w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPCFJdRZXSCDa94N=
dB_YRn-3DSWaVGWMvFM2sTz7CYovjqqy6w%40mail.gmail.com</a>.<br />
--94eb2c12f94cece42c054bb9b0d1--
.
Author: Maxim Yanchenko <maxim.yanchenko@gmail.com>
Date: Tue, 28 Mar 2017 01:29:55 +0800
Raw View
--001a113d125c84d8fd054bb9b3f5
Content-Type: text/plain; charset=UTF-8
Hi Jon,
> A byte-strided array_view would lose many of the advantages of memory
contiguity.
Yes, I mentioned this in the Note 2. You can always check if the view is
contiguous by calling av.contiguous() if you want to do something specific
to a contiguous chunk of memory.
> I think there are already some proposals in flight to convert vectors of
structs into structs of vectors.
Yes, and it's useful, but this is orthogonal to array_view.
Both have their different spheres of application.
Thanks,
Maxim
On Tue, Mar 28, 2017 at 1:17 AM, Jonathan Coe <jonathanbcoe@gmail.com>
wrote:
>
>
> On 27 March 2017 at 18:10, Maxim Yanchenko <maxim.yanchenko@gmail.com>
> wrote:
>
>> Good day to everyone,
>>
>> I checked the existing proposals regarding array_view (including the
>> multi-dimensional and strided ones) and I found none that would support
>> byte stride (please correct me if I missed one, apologies in advance).
>> I have my own custom array view written long time ago which I use a lot
>> and found it extremely convenient, and it differs from the proposed
>> array_view by having an additional runtime parameter byte_stride
>> (defaulted to sizeof(T) to have usual array_view by default).
>> The byte_stride is not part of the type, so the type is still the same array_view<class
>> T, int Rank=1> and you can use it for both contiguous arrays and byte-strided
>> arrays.
>>
>> So the constructor looks like this (for 1D array view):
>> array_view( T* ptr, size_t size, size_t byte_stride = sizeof(T) );
>>
>> *Motivation*
>> In scientific/financial calculations one often has arrays of sets of
>> parameters, i.e. arrays of structs:
>> struct BasicData {
>> int data1;
>> int data2;
>> };
>> BasicData barr[50];
>> It's also not unusual to have extended versions of algorithms that use
>> additional parameters on top of the generic ones (or save additional data
>> on top of the common one).
>> The natural way of dealing with this is just inheriting from the basic
>> struct and make an array of the derived struct:
>> struct ExtendedData : BasicData {
>> int data3;
>> };
>> ExtendedData earr[50];
>> this way you can access common and extended data the same way without
>> changing your code (and you can freely move parameters from derived struct
>> to the base and back, without affecting the specialized code that uses
>> them):
>> earr.data1[i] = earr.data2[i] * earr.data3[i];
>>
>> The problem here is that now even the code that doesn't need extended
>> data (like ones gathering common statistics or statuses) and would happily
>> run on just basic data (and therefore could have been factored out to the
>> common unspecialized codebase)
>> void common_processing(array_view<BasicData>);
>> Such a function can't run because there is no array of basic params
>> anymore, they are hidden inside the bigger extended params struct, and
>> there is currently no way to get an array_view<BasicData> out of earr.
>> Strided array_view won't help because sizeof(BasicData) is 2*sizeof(int),
>> while sizeof(ExtendedData) is 3*sizeof(int) - so strides of sizeof(
>> BasicData) won't work.
>>
>> Also, there can be a plugin-like architecture of the program so the host
>> wouldn't even know the type ExtendedData that exists only in the plugin
>> but still could access BasicData owned by the plugin if there was a way
>> to construct
>> array_view<BasicData>.
>>
>> All the above is easily achievable with a byte-strided array_view.
>>
>>
>> Another example: think of BasicData as RGB and ExtendedData as RGBA/ARGB:
>> you could have an array_view<RGB> over an RGBA file and an RGB file and
>> even an ARGB file, agnostically - they will only differ in their
>> byte_stride value.
>>
>>
>>
>> Here are the use cases (1D, for simplicity):
>>
>> *1) Use as a normal array_view:*
>> struct B {
>> int x,y;
>> };
>> B *pb = new B[50];
>> array_view<B> av( pb, 50 ); // byte_stride is defaulted to sizeof(B)
>>
>> *2) view of an array of a derived class D as an array of base class B:*
>> struct B {
>> int x,y;
>> };
>> struct D: B {
>> int a;
>> };
>> D *pd = new D[50];
>> array_view<B> av_b( pd, 50, sizeof(D) );
>>
>> (pd automatically converted to B*, sizeof(B) == 2*sizeof(int), sizeof(D)
>> == 3*sizeof(int) so usual integer stride won't work here because
>> sizeof(D) is not a multiple of sizeof(B))
>>
>> to avoid mistakes, an obvious helper function array_view_by_base() is
>> provided (it also checks static_assert(std::is_base_of_v<B,D>)):
>> array_view<B> av_b = array_view_by_base<B>( pd, 50 );
>>
>> *3) Member view ("array" of field b):*
>> struct B {
>> int x,y;
>> };
>> struct C {
>> int a;
>> B b;
>> };
>> C *pc = new C[50];
>> array_view<B> av_b( &pc[0].b, 50, sizeof(C) );
>> array_view<int> av_y( &pc[0].b.y, 50, sizeof(C) );
>>
>> Again, to avoid mistakes, a helper function array_view_by_member() is
>> provided:
>> array_view<B> av_b = array_view_by_member( pc, &C::b, 50 ); // both D
>> and B are deduced from the arguments
>>
>> Unfortunately, there is currently no way in C++ to have a nested
>> pointer-to-member so it's impossible to write something like &C::b::y.
>> This can be emulated, to some extent, by providing a tuple like (&C::b,
>> &B::y) but it's not much more readable than the unsafe version. So the
>> safe version for av_y would be:
>> array_view<int> av_y = array_view_by_member( pc, std::make_tuple(&C::b,
>> &B::y), 50 ); // both D and int are deduced from the arguments
>>
>> *4) Strided views for all the cases above*:
>> Just call the constructor with stride*sizeof(D) instead of just sizeof(D)
>>
>>
>> *Note 1:* when the argument p above is not a plain pointer but a
>> container that knows its size (via std::size - think of std::vector,
>> std::array, or even another array_view) then you don't need to provide the
>> size manually:
>> std::vector<B> vb;
>> array_view<B> av_b( vb );
>> std::vector<D> vd;
>> array_view<B> av_b = array_view_by_base<B>( vd );
>> std::vector<C> vc;
>> array_view<B> av_b = array_view_by_member( vc, &C::b );
>>
>> *Note 2:* advantage over some other proposals is in the uniform type
>> array_view<T,Rank> that doesn't depend on the "continuousness" (unlike
>> n4177 where strided view is a separate type strided_array_view).
>> For those who need to know if the view is contiguous (for example, to do
>> a bulk memcpy instead of element-wise copying) there is a member
>> function bool continuous() const provided that just checks if
>> sizeof(T)==byte_stride.
>>
>> *Note 3:* array_view supports default construction and assignment (this
>> is necessary for the cases when we have a view in the host program, then we
>> load a plugin, attach to its memory, and initialized our array_view to look
>> at the plugin's memory, and then we can unload the plugin and load another,
>> with a different derived type, and reinitialized our array_view again).
>>
>>
>> Comments?
>> If there is an agreement that it would be good to have (from my
>> experience, it is) I'll write a formal proposal.
>>
>>
> A byte-strided array_view would lose many of the advantages of memory
> contiguity. I'd be inclined to use a struct of array_views rather than a
> strided array view of structs.
>
> struct C_view {
> array_view<int> as;
> array_view<B> bs;
> };
>
> I think there are already some proposals in flight to convert vectors of
> structs into structs of vectors.
>
> Regards,
>
> Jon
>
> Thanks everyone,
>> Yours sincerely,
>> Maxim Yanchenko
>>
>> --
>> 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-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/is
>> ocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG
>> 9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>
> --
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%
> 2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDfFFdptzZSdLf98_ph_g%2B_M%3Dt9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com.
--001a113d125c84d8fd054bb9b3f5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div>Hi Jon,<br></div><div><br>> <s=
pan style=3D"font-size:12.8px;font-family:arial,helvetica,sans-serif">A byt=
e-strided=C2=A0</span><span style=3D"font-size:12.8px;font-family:monospace=
,monospace">array_view </span><span style=3D"font-family:arial black,sans-s=
erif"><span style=3D"font-size:12.8px">would lose many of the advantages of=
memory contiguity.<br></span></span></div><span style=3D"font-family:arial=
black,sans-serif"><span style=3D"font-size:12.8px">Yes, </span></span><spa=
n style=3D"font-family:arial black,sans-serif"><span style=3D"font-size:12.=
8px">I mentioned this in the Note 2. You can always check if the view is co=
ntiguous by calling <span style=3D"font-family:monospace,monospace">av.cont=
iguous()</span><span style=3D"font-family:tahoma,sans-serif"> <span style=
=3D"font-family:arial,helvetica,sans-serif">if you want to do something spe=
cific to a contiguous chunk of memory</span></span>.</span></span><br></div=
><div><span style=3D"font-family:arial black,sans-serif"><span style=3D"fon=
t-size:12.8px"></span></span></div><span style=3D"font-family:arial black,s=
ans-serif"><span style=3D"font-size:12.8px"><br></span></span>> I think =
there are already some proposals in flight to convert vectors of structs in=
to structs of vectors.<br></div>Yes, and it's useful, but this is ortho=
gonal to array_view.<br></div><div>Both have their different spheres of app=
lication.<br></div><div><br></div>Thanks,<br></div>Maxim<br></div><div clas=
s=3D"gmail_extra"><br><div class=3D"gmail_quote">On Tue, Mar 28, 2017 at 1:=
17 AM, Jonathan Coe <span dir=3D"ltr"><<a href=3D"mailto:jonathanbcoe@gm=
ail.com" target=3D"_blank">jonathanbcoe@gmail.com</a>></span> wrote:<br>=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><div class=3D"gmail_ext=
ra"><br><div class=3D"gmail_quote"><div><div class=3D"h5">On 27 March 2017 =
at 18:10, Maxim Yanchenko <span dir=3D"ltr"><<a href=3D"mailto:maxim.yan=
chenko@gmail.com" target=3D"_blank">maxim.yanchenko@gmail.com</a>></span=
> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div><div><div><div><div><div=
>Good day to everyone,<br><br>I checked the existing proposals regarding <s=
pan style=3D"font-family:monospace,monospace">array_view</span> (including =
the multi-dimensional and strided ones) and I found none that would support=
byte stride (please correct me if I missed one, apologies in advance).<br>=
</div>I have my own custom array view written long time ago which I use a l=
ot and found it extremely convenient, and it differs from the proposed <spa=
n style=3D"font-family:monospace,monospace">array_view</span> by having an =
additional runtime parameter <span style=3D"font-family:monospace,monospace=
">byte_stride</span> (defaulted to <span style=3D"font-family:monospace,mon=
ospace">sizeof(T)</span> to have usual <span style=3D"font-family:monospace=
,monospace">array_view</span> by default).<br></div>The <span style=3D"font=
-family:monospace,monospace">byte_stride</span> is not part of the type, so=
the type is still the same <span style=3D"font-family:monospace,monospace"=
>array_view<class T, int Rank=3D1></span><span style=3D"font-family:a=
rial,helvetica,sans-serif"> and</span> you can use it for both contiguous a=
rrays and <span style=3D"font-family:arial,helvetica,sans-serif">byte-strid=
ed </span>arrays.<br><br></div><div>So the constructor looks like this (for=
1D array view): <br></div><div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">array_view( T* ptr, size_t size, size_=
t byte_stride =3D sizeof(T) );</span><br></div><br></div><div><b>Motivation=
</b><br></div><div>In scientific/financial calculations one often has array=
s of sets of parameters, i.e. arrays of structs:<br></div><div style=3D"mar=
gin-left:40px"><span style=3D"font-family:monospace,monospace">struct Basic=
Data {<br></span></div><div style=3D"margin-left:40px"><span style=3D"font-=
family:monospace,monospace">=C2=A0 int data1;<br></span></div><div style=3D=
"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 i=
nt data2;<br></span></div><div style=3D"margin-left:40px"><span style=3D"fo=
nt-family:monospace,monospace">};<br></span><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace">BasicData =
</span>barr[50]; </span></div><div>It's also not unusual to have extend=
ed versions of algorithms that use additional parameters on top of the gene=
ric ones (or save additional data on top of the common one).<br></div><div>=
The natural way of dealing with this is just inheriting from the basic stru=
ct and make an array of the derived struct:<br></div><div style=3D"margin-l=
eft:40px"><span style=3D"font-family:monospace,monospace">struct </span><sp=
an style=3D"font-family:monospace,monospace"><span style=3D"font-family:mon=
ospace,monospace">ExtendedData </span><span style=3D"font-family:arial,helv=
etica,sans-serif"></span>: </span><span style=3D"font-family:monospace,mono=
space"><span style=3D"font-family:monospace,monospace">BasicData </span>{<b=
r></span></div><div style=3D"margin-left:40px"><span style=3D"font-family:m=
onospace,monospace">=C2=A0 int data3;<br></span></div><div><div style=3D"ma=
rgin-left:40px"><span style=3D"font-family:monospace,monospace">};<br></spa=
n><span style=3D"font-family:monospace,monospace"><span style=3D"font-famil=
y:monospace,monospace"><span style=3D"font-family:monospace,monospace">Exte=
ndedData e</span></span>arr[50];</span><br></div> this way you can access c=
ommon and extended data the same way=20
without changing your code (and you can freely move parameters from=20
derived struct to the base and back, without affecting the specialized=20
code that uses them):<br></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">earr.data1[i] =3D earr.data2[i] * earr=
..data3[i];<br><br></span></div><div>The problem here is that now even the c=
ode that doesn't need extended data (like ones gathering common statist=
ics or statuses) and would happily run on just basic data (and therefore co=
uld have been factored out to the common unspecialized codebase)<br><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">vo=
id common_processing(array_view<</span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace">B<wbr>asicDa=
ta</span>>);</span><br></div>Such a function can't run because there=
is no array of basic params anymore, they are hidden inside the bigger ext=
ended params struct, and there is currently no way to get an <span style=3D=
"font-family:monospace,monospace">array_view<BasicData></span> out of=
<span style=3D"font-family:monospace,monospace">earr</span>.<br></div><div=
>Strided array_view won't help because <span style=3D"font-family:monos=
pace,monospace">sizeof(BasicData) </span><span style=3D"font-family:arial,h=
elvetica,sans-serif">is </span><span style=3D"font-family:monospace,monospa=
ce">2*sizeof(int), while sizeof(</span><span style=3D"font-family:monospace=
,monospace">ExtendedData</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"></span><span style=3D"font-family:monospace,monospace">) </span>=
<span style=3D"font-family:arial,helvetica,sans-serif">is </span><span styl=
e=3D"font-family:monospace,monospace">3*sizeof(int)</span><span style=3D"fo=
nt-family:arial,helvetica,sans-serif"> - so strides of </span><span style=
=3D"font-family:monospace,monospace">sizeof(</span><span style=3D"font-fami=
ly:monospace,monospace">BasicData</span><span style=3D"font-family:monospac=
e,monospace">)</span><span style=3D"font-family:arial,helvetica,sans-serif"=
> won't work.</span><span style=3D"font-family:monospace,monospace"><br=
></span></div><div><br></div><div>Also, there can be a plugin-like architec=
ture of the program so the host wouldn't even know the type <span style=
=3D"font-family:monospace,monospace">ExtendedData </span><span style=3D"fon=
t-family:arial,helvetica,sans-serif"></span><span style=3D"font-family:aria=
l,helvetica,sans-serif">that exists only in the plugin but still could acce=
ss</span><span style=3D"font-family:monospace,monospace"> </span><span styl=
e=3D"font-family:monospace,monospace">BasicData </span><span style=3D"font-=
family:arial,helvetica,sans-serif">owned by the plugin if there was a way t=
o construct </span><br><span style=3D"font-family:monospace,monospace">arra=
y_view<</span><span style=3D"font-family:monospace,monospace"><span styl=
e=3D"font-family:monospace,monospace">BasicData</span>>.</span></div><di=
v><br>All the above is easily achievable with <span style=3D"font-family:ar=
ial,helvetica,sans-serif">a byte-strided </span><span style=3D"font-family:=
monospace,monospace">array_view</span>.<br><br><br></div><div>Another examp=
le: think of <span style=3D"font-family:monospace,monospace">BasicData </sp=
an>as<span style=3D"font-family:monospace,monospace"> RGB </span>and <span =
style=3D"font-family:monospace,monospace">ExtendedData </span><span style=
=3D"font-family:arial,helvetica,sans-serif">as<span style=3D"font-family:mo=
nospace,monospace"> </span></span><span style=3D"font-family:monospace,mono=
space">RGBA/ARGB:</span> you could have an <span style=3D"font-family:monos=
pace,monospace">array_view<RGB></span> over an RGBA file and an RGB f=
ile and even an ARGB file, agnostically - they will only differ in their <s=
pan style=3D"font-family:monospace,monospace">byte_stride</span> value.<br>=
<br><br></div><div><br></div>Here are the use cases (1D, for simplicity):<b=
r><br></div><div><b>1) Use as a normal <span style=3D"font-family:monospace=
,monospace">array_view</span>:</b><br></div><div style=3D"margin-left:40px"=
><span style=3D"font-family:monospace,monospace"><span style=3D"font-family=
:monospace,monospace">struct B {<br></span><span style=3D"font-family:monos=
pace,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monosp=
ace,monospace">};<br></span></span><span style=3D"font-family:monospace,mon=
ospace">B *pb =3D new B[50];</span></div><div><div style=3D"margin-left:40p=
x"><span style=3D"font-family:monospace,monospace">array_view<B> av( =
pb, 50 ); // byte_stride</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"> is defaulted to</span><span style=3D"font-family:monospace,mono=
space"> sizeof(B)</span><br></div><div style=3D"margin-left:40px"><span sty=
le=3D"font-family:monospace,monospace"></span></div><span style=3D"font-fam=
ily:monospace,monospace"><br></span></div><b>2) view of an array of a deriv=
ed class D as an array of base class B:</b><br></div><span style=3D"font-fa=
mily:monospace,monospace"></span></div><div style=3D"margin-left:40px"><spa=
n style=3D"font-family:monospace,monospace"><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace">struct B {=
<br></span><span style=3D"font-family:monospace,monospace">=C2=A0 int x,y;<=
br></span><span style=3D"font-family:monospace,monospace">};<br></span></sp=
an><span style=3D"font-family:monospace,monospace"></span>struct D: B {<br>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">=C2=A0 int a;<br>};<br></span></div><div style=3D"margin-=
left:40px"><span style=3D"font-family:monospace,monospace">D *pd =3D new D[=
50];<br></span></div><div><div style=3D"margin-left:40px"><span style=3D"fo=
nt-family:monospace,monospace">array_view<B> av_b( pd, 50, sizeof(D) =
);<br><br></span><span style=3D"font-family:monospace,monospace"></span></d=
iv><span style=3D"font-family:arial,helvetica,sans-serif">(</span><span sty=
le=3D"font-family:monospace,monospace">pd </span><span style=3D"font-family=
:arial,helvetica,sans-serif">automatically converted to </span><span style=
=3D"font-family:monospace,monospace">B*, sizeof(B) =3D=3D 2*sizeof(int), si=
zeof(D) =3D=3D 3*sizeof(int)</span><span style=3D"font-family:arial,helveti=
ca,sans-serif"> so usual integer stride won't work here because <span s=
tyle=3D"font-family:monospace,monospace">sizeof(D)</span> is not a multiple=
of <span style=3D"font-family:monospace,monospace">sizeof(B)</span>)</span=
><br><br></div><div>to avoid mistakes, an obvious helper function <span sty=
le=3D"font-family:monospace,monospace">array_view_by_base()</span> is provi=
ded (it also checks <span style=3D"font-family:monospace,monospace">static_=
assert(std::is_base_of_<wbr>v<B,D>)</span>):<br></div><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">array_view=
<B> av_b =3D array_view_by_base<B>( pd, 50 );</span></div><div>=
<br></div><div><b>3) Member view ("array" of field b):</b><br><di=
v style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace=
"><span style=3D"font-family:monospace,monospace"><span style=3D"font-famil=
y:monospace,monospace">struct B {<br></span><span style=3D"font-family:mono=
space,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monos=
pace,monospace">};<br></span></span><span style=3D"font-family:monospace,mo=
nospace"></span>struct C {<br></span></div><div style=3D"margin-left:40px">=
<span style=3D"font-family:monospace,monospace">=C2=A0 int a;</span><br><sp=
an style=3D"font-family:monospace,monospace"></span></div></div><div style=
=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=
=A0 B b;<br></span></div><div style=3D"margin-left:40px"><span style=3D"fon=
t-family:monospace,monospace">};</span><span style=3D"font-family:monospace=
,monospace"><br></span><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">C *pc =3D new C[50];<br></span>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">array_view<B>=C2=A0=C2=A0 av_b( </span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">&pc[0].b,=C2=A0=C2=A0 50, sizeof(C) </span>);<br></span></div=
><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,monos=
pace">array_view<int> av_y( </span><span style=3D"font-family:monospa=
ce,monospace"><span style=3D"font-family:monospace,monospace">&pc[0].b.=
y, 50, sizeof(C) </span>);<br></span></div><span style=3D"font-family:monos=
pace,monospace"></span><span style=3D"font-family:monospace,monospace"><fon=
t face=3D"arial,helvetica,sans-serif"><br>Again, to avoid mistakes, a helpe=
r function </font>array_view_by_member()</span><span style=3D"font-family:a=
rial,helvetica,sans-serif"> is provided</span>:<br><span style=3D"font-fami=
ly:monospace,monospace"></span><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view<B>=C2=A0=C2=A0 av_b =3D array_view_by_member( pc=
, &C::b, 50 );</span></span> // both D and B are deduced from the argum=
ents<br><br></div><div>Unfortunately, there is currently no way in C++ to h=
ave a nested pointer-to-member so it's impossible to write something li=
ke <span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace">&C::b::y</span></span><span style=3D"font-famil=
y:arial,helvetica,sans-serif">. This can be emulated, to some extent, by pr=
oviding a tuple like <span style=3D"font-family:monospace,monospace">(&=
C::b, &B::y)</span> but it's not much more readable than the unsafe=
version. So the safe version for <span style=3D"font-family:'times new=
roman',serif">av_y</span> would be</span><span style=3D"font-family:&#=
39;times new roman',serif">:</span><span style=3D"font-family:monospace=
,monospace"><span style=3D"font-family:monospace,monospace"><br></span></sp=
an><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace">array_view<int&g=
t; av_y =3D array_view_by_member( pc, std::make_tuple(&C::b,</span></sp=
an><span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:arial,helvetica,sans-ser=
if"><span style=3D"font-family:monospace,monospace"> &B::y)</span></spa=
n>, 50 );</span></span> // both D and int are deduced from the arguments</d=
iv></div><div><br></div><div><b>4) Strided views for all the cases above</b=
>:<br></div><div>Just call the constructor with stride*sizeof(D) instead of=
just sizeof(D)<br></div><div><br><br></div><div><b>Note 1:</b> when the ar=
gument p above is not a plain pointer but a container that knows its size (=
via std::size - think of std::vector, std::array, or even another array_vie=
w) then you don't need to provide the size manually:<br><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">std::vecto=
r<B> vb;</span><br><span style=3D"font-family:monospace,monospace">ar=
ray_view<B> av_b( vb );</span><br><span style=3D"font-family:monospac=
e,monospace">std::vector<D> vd;</span><br><span style=3D"font-family:=
monospace,monospace"><span style=3D"font-family:monospace,monospace"><span =
style=3D"font-family:monospace,monospace"><span style=3D"font-family:monosp=
ace,monospace">array_view<B> av_b =3D </span>array_view_by_base<B&=
gt;( vd );</span></span></span><br><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace"><span style=3D"font=
-family:monospace,monospace"></span></span></span><span style=3D"font-famil=
y:monospace,monospace"><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">std::vector<C> vc;</span>=
<br><span style=3D"font-family:monospace,monospace"><span style=3D"font-fam=
ily:monospace,monospace"><span style=3D"font-family:monospace,monospace"><s=
pan style=3D"font-family:monospace,monospace"></span></span></span></span>a=
rray_view<B> av_b =3D </span></span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view_by_member</span></span></span>( vc</span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace"><span style=3D"font-family:monospace,monospace">, &C::b</span=
></span> );</span><br></div><div style=3D"margin-left:40px"><span style=3D"=
font-family:monospace,monospace"></span></div><span style=3D"font-family:mo=
nospace,monospace"><br></span></div><div><span style=3D"font-family:arial,h=
elvetica,sans-serif"><b>Note 2:</b> advantage over some other proposals is =
in the uniform type <span style=3D"font-family:monospace,monospace">array_v=
iew<T,Rank></span> that doesn't depend on the "continuousnes=
s" (unlike n4177 where strided view is a separate type </span><span st=
yle=3D"font-family:arial,helvetica,sans-serif"><code>strided_array_view</co=
de>). <br>For those who need to know if the view is contiguous (for example=
, to do a bulk <span style=3D"font-family:monospace,monospace">memcpy</span=
> instead of element-wise copying) there is a member function=C2=A0 <span s=
tyle=3D"font-family:monospace,monospace">bool continuous() const</span> pro=
vided that just checks if <span style=3D"font-family:monospace,monospace">s=
izeof(T)=3D=3Dbyte_stride</span>.<br></span><span style=3D"font-family:aria=
l,helvetica,sans-serif"><br></span></div><div><span style=3D"font-family:ar=
ial,helvetica,sans-serif"><b>Note 3:</b> array_view supports default constr=
uction and assignment (this is necessary for the cases when we have a view =
in the host program, then we load a plugin, attach to its memory, and initi=
alized our array_view to look at the plugin's memory, and then we can u=
nload the plugin and load another, with a different derived type, and reini=
tialized our array_view again).<br><br></span></div><div><span style=3D"fon=
t-family:arial,helvetica,sans-serif"><br></span></div><div><span style=3D"f=
ont-family:arial,helvetica,sans-serif">Comments?<br>If there is </span><spa=
n style=3D"font-family:arial,helvetica,sans-serif"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:monospace,monospace"></s=
pan></span></span>an agreement that it would be good to have (from my exper=
ience, it is) I'll write a formal proposal.<br><br></div></div></blockq=
uote><div><br></div></div></div><div><span style=3D"font-size:12.8000001907=
34863px;font-family:arial,helvetica,sans-serif">A byte-strided=C2=A0</span>=
<span style=3D"font-size:12.800000190734863px;font-family:monospace,monospa=
ce">array_view would lose many of the advantages of memory contiguity. I=
9;d be inclined to use a struct of array_views rather than a strided array =
view of structs.</span><br></div><div>=C2=A0</div><div><div><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">struct C_v=
iew {<br></span></div><div style=3D"margin-left:40px"><span style=3D"font-f=
amily:monospace,monospace">=C2=A0 array_view<int> as;</span><br><span=
style=3D"font-family:monospace,monospace"></span></div></div><div style=3D=
"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 a=
rray_view<B> bs;</span></div><div style=3D"margin-left:40px"><span st=
yle=3D"font-family:monospace,monospace">};</span></div></div><div><br></div=
><div>I think there are already some proposals in flight to convert vectors=
of structs into structs of vectors.</div><div><br></div><div>Regards,</div=
><div><br></div><div>Jon</div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col=
or:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=
=3D""><div dir=3D"ltr"><div></div><div>Thanks everyone,<br></div><div>Yours=
sincerely,<br></div><div>Maxim Yanchenko<span class=3D"m_-3273197037045350=
056gmail-HOEnZb"><font color=3D"#888888"><br></font></span></div><span clas=
s=3D"m_-3273197037045350056gmail-HOEnZb"><font color=3D"#888888"><div><span=
style=3D"font-family:monospace,monospace"><br></span></div></font></span><=
/div></span><span class=3D"HOEnZb"><font color=3D"#888888"><span class=3D"m=
_-3273197037045350056gmail-HOEnZb"><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3=
Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter" target=3D"_blank">https://groups.google.com/a/is<wbr>ocpp.org/d/msgi=
d/std-proposals<wbr>/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG<wbr>9N6X_Q%3Dg5Umvmd78GX=
fDG2K2xw%<wbr>40mail.gmail.com</a>.<br>
</font></span></font></span></blockquote></div><span class=3D"HOEnZb"><font=
color=3D"#888888"><br></font></span></div></div><span class=3D"HOEnZb"><fo=
nt color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPC=
zKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r" target=3D"_blank">https://groups.google.com/a/<wbr>isocpp.org/d/msgid/st=
d-<wbr>proposals/CAAbBDD9_iSMBN%<wbr>2Bx4tHXZoQKoqE7caKWHPCzKjXWasO<wbr>iuj=
-Hq7w%40mail.gmail.com</a>.<br>
</font></span></blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDfFFdptzZSdLf98_ph_g%2B_M%3Dt=
9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTD=
fFFdptzZSdLf98_ph_g%2B_M%3Dt9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com</a>.<br=
/>
--001a113d125c84d8fd054bb9b3f5--
.
Author: Jonathan Coe <jonathanbcoe@gmail.com>
Date: Mon, 27 Mar 2017 18:37:37 +0100
Raw View
--001a114125fe036db7054bb9cf80
Content-Type: text/plain; charset=UTF-8
On 27 March 2017 at 18:29, Maxim Yanchenko <maxim.yanchenko@gmail.com>
wrote:
> Hi Jon,
>
> > A byte-strided array_view would lose many of the advantages of memory
> contiguity.
> Yes, I mentioned this in the Note 2. You can always check if the view is
> contiguous by calling av.contiguous() if you want to do something
> specific to a contiguous chunk of memory.
>
> > I think there are already some proposals in flight to convert vectors of
> structs into structs of vectors.
> Yes, and it's useful, but this is orthogonal to array_view.
> Both have their different spheres of application.
>
>
Understood.
> Thanks,
> Maxim
>
> On Tue, Mar 28, 2017 at 1:17 AM, Jonathan Coe <jonathanbcoe@gmail.com>
> wrote:
>
>>
>>
>> On 27 March 2017 at 18:10, Maxim Yanchenko <maxim.yanchenko@gmail.com>
>> wrote:
>>
>>> Good day to everyone,
>>>
>>> I checked the existing proposals regarding array_view (including the
>>> multi-dimensional and strided ones) and I found none that would support
>>> byte stride (please correct me if I missed one, apologies in advance).
>>> I have my own custom array view written long time ago which I use a lot
>>> and found it extremely convenient, and it differs from the proposed
>>> array_view by having an additional runtime parameter byte_stride
>>> (defaulted to sizeof(T) to have usual array_view by default).
>>> The byte_stride is not part of the type, so the type is still the same array_view<class
>>> T, int Rank=1> and you can use it for both contiguous arrays and byte-strided
>>> arrays.
>>>
>>> So the constructor looks like this (for 1D array view):
>>> array_view( T* ptr, size_t size, size_t byte_stride = sizeof(T) );
>>>
>>> *Motivation*
>>> In scientific/financial calculations one often has arrays of sets of
>>> parameters, i.e. arrays of structs:
>>> struct BasicData {
>>> int data1;
>>> int data2;
>>> };
>>> BasicData barr[50];
>>> It's also not unusual to have extended versions of algorithms that use
>>> additional parameters on top of the generic ones (or save additional data
>>> on top of the common one).
>>> The natural way of dealing with this is just inheriting from the basic
>>> struct and make an array of the derived struct:
>>> struct ExtendedData : BasicData {
>>> int data3;
>>> };
>>> ExtendedData earr[50];
>>> this way you can access common and extended data the same way without
>>> changing your code (and you can freely move parameters from derived struct
>>> to the base and back, without affecting the specialized code that uses
>>> them):
>>> earr.data1[i] = earr.data2[i] * earr.data3[i];
>>>
>>> The problem here is that now even the code that doesn't need extended
>>> data (like ones gathering common statistics or statuses) and would happily
>>> run on just basic data (and therefore could have been factored out to the
>>> common unspecialized codebase)
>>> void common_processing(array_view<BasicData>);
>>> Such a function can't run because there is no array of basic params
>>> anymore, they are hidden inside the bigger extended params struct, and
>>> there is currently no way to get an array_view<BasicData> out of earr.
>>> Strided array_view won't help because sizeof(BasicData) is 2*sizeof(int),
>>> while sizeof(ExtendedData) is 3*sizeof(int) - so strides of sizeof(
>>> BasicData) won't work.
>>>
>>> Also, there can be a plugin-like architecture of the program so the host
>>> wouldn't even know the type ExtendedData that exists only in the plugin
>>> but still could access BasicData owned by the plugin if there was a way
>>> to construct
>>> array_view<BasicData>.
>>>
>>> All the above is easily achievable with a byte-strided array_view.
>>>
>>>
>>> Another example: think of BasicData as RGB and ExtendedData as
>>> RGBA/ARGB: you could have an array_view<RGB> over an RGBA file and an
>>> RGB file and even an ARGB file, agnostically - they will only differ in
>>> their byte_stride value.
>>>
>>>
>>>
>>> Here are the use cases (1D, for simplicity):
>>>
>>> *1) Use as a normal array_view:*
>>> struct B {
>>> int x,y;
>>> };
>>> B *pb = new B[50];
>>> array_view<B> av( pb, 50 ); // byte_stride is defaulted to sizeof(B)
>>>
>>> *2) view of an array of a derived class D as an array of base class B:*
>>> struct B {
>>> int x,y;
>>> };
>>> struct D: B {
>>> int a;
>>> };
>>> D *pd = new D[50];
>>> array_view<B> av_b( pd, 50, sizeof(D) );
>>>
>>> (pd automatically converted to B*, sizeof(B) == 2*sizeof(int),
>>> sizeof(D) == 3*sizeof(int) so usual integer stride won't work here
>>> because sizeof(D) is not a multiple of sizeof(B))
>>>
>>> to avoid mistakes, an obvious helper function array_view_by_base() is
>>> provided (it also checks static_assert(std::is_base_of_v<B,D>)):
>>> array_view<B> av_b = array_view_by_base<B>( pd, 50 );
>>>
>>> *3) Member view ("array" of field b):*
>>> struct B {
>>> int x,y;
>>> };
>>> struct C {
>>> int a;
>>> B b;
>>> };
>>> C *pc = new C[50];
>>> array_view<B> av_b( &pc[0].b, 50, sizeof(C) );
>>> array_view<int> av_y( &pc[0].b.y, 50, sizeof(C) );
>>>
>>> Again, to avoid mistakes, a helper function array_view_by_member() is
>>> provided:
>>> array_view<B> av_b = array_view_by_member( pc, &C::b, 50 ); // both D
>>> and B are deduced from the arguments
>>>
>>> Unfortunately, there is currently no way in C++ to have a nested
>>> pointer-to-member so it's impossible to write something like &C::b::y.
>>> This can be emulated, to some extent, by providing a tuple like (&C::b,
>>> &B::y) but it's not much more readable than the unsafe version. So the
>>> safe version for av_y would be:
>>> array_view<int> av_y = array_view_by_member( pc, std::make_tuple(&C::b,
>>> &B::y), 50 ); // both D and int are deduced from the arguments
>>>
>>> *4) Strided views for all the cases above*:
>>> Just call the constructor with stride*sizeof(D) instead of just sizeof(D)
>>>
>>>
>>> *Note 1:* when the argument p above is not a plain pointer but a
>>> container that knows its size (via std::size - think of std::vector,
>>> std::array, or even another array_view) then you don't need to provide the
>>> size manually:
>>> std::vector<B> vb;
>>> array_view<B> av_b( vb );
>>> std::vector<D> vd;
>>> array_view<B> av_b = array_view_by_base<B>( vd );
>>> std::vector<C> vc;
>>> array_view<B> av_b = array_view_by_member( vc, &C::b );
>>>
>>> *Note 2:* advantage over some other proposals is in the uniform type
>>> array_view<T,Rank> that doesn't depend on the "continuousness" (unlike
>>> n4177 where strided view is a separate type strided_array_view).
>>> For those who need to know if the view is contiguous (for example, to do
>>> a bulk memcpy instead of element-wise copying) there is a member
>>> function bool continuous() const provided that just checks if
>>> sizeof(T)==byte_stride.
>>>
>>> *Note 3:* array_view supports default construction and assignment (this
>>> is necessary for the cases when we have a view in the host program, then we
>>> load a plugin, attach to its memory, and initialized our array_view to look
>>> at the plugin's memory, and then we can unload the plugin and load another,
>>> with a different derived type, and reinitialized our array_view again).
>>>
>>>
>>> Comments?
>>> If there is an agreement that it would be good to have (from my
>>> experience, it is) I'll write a formal proposal.
>>>
>>>
>> A byte-strided array_view would lose many of the advantages of memory
>> contiguity. I'd be inclined to use a struct of array_views rather than a
>> strided array view of structs.
>>
>> struct C_view {
>> array_view<int> as;
>> array_view<B> bs;
>> };
>>
>> I think there are already some proposals in flight to convert vectors of
>> structs into structs of vectors.
>>
>> Regards,
>>
>> Jon
>>
>> Thanks everyone,
>>> Yours sincerely,
>>> Maxim Yanchenko
>>>
>>> --
>>> 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-proposals+unsubscribe@isocpp.org.
>>> To post to this group, send email to std-proposals@isocpp.org.
>>> To view this discussion on the web visit https://groups.google.com/a/is
>>> ocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG
>>> 9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com
>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>> --
>> 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-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/is
>> ocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE
>> 7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPCzKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>
> --
> 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-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/CA%2B6mTDfFFdptzZSdLf98_ph_g%2B_
> M%3Dt9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDfFFdptzZSdLf98_ph_g%2B_M%3Dt9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD_Jg90vddVRwkRpDEaegUGk4Xx9oi-FfK7Js_Ky0o0Dug%40mail.gmail.com.
--001a114125fe036db7054bb9cf80
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On 27 March 2017 at 18:29, Maxim Yanchenko <span dir=3D"ltr"><<a hre=
f=3D"mailto:maxim.yanchenko@gmail.com" target=3D"_blank">maxim.yanchenko@gm=
ail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr"><div><div><div><div><div>Hi Jon,<br></div><span class=3D""><div><br>&=
gt; <span style=3D"font-size:12.8px;font-family:arial,helvetica,sans-serif"=
>A byte-strided=C2=A0</span><span style=3D"font-size:12.8px;font-family:mon=
ospace,monospace">array_view </span><span style=3D"font-family:arial black,=
sans-serif"><span style=3D"font-size:12.8px">would lose many of the advanta=
ges of memory contiguity.<br></span></span></div></span><span style=3D"font=
-family:arial black,sans-serif"><span style=3D"font-size:12.8px">Yes, </spa=
n></span><span style=3D"font-family:arial black,sans-serif"><span style=3D"=
font-size:12.8px">I mentioned this in the Note 2. You can always check if t=
he view is contiguous by calling <span style=3D"font-family:monospace,monos=
pace">av.contiguous()</span><span style=3D"font-family:tahoma,sans-serif"> =
<span style=3D"font-family:arial,helvetica,sans-serif">if you want to do so=
mething specific to a contiguous chunk of memory</span></span>.</span></spa=
n><br></div><span class=3D""><div><span style=3D"font-family:arial black,sa=
ns-serif"><span style=3D"font-size:12.8px"></span></span></div><span style=
=3D"font-family:arial black,sans-serif"><span style=3D"font-size:12.8px"><b=
r></span></span>> I think there are already some proposals in flight to =
convert vectors of structs into structs of vectors.<br></span></div>Yes, an=
d it's useful, but this is orthogonal to array_view.<br></div><div>Both=
have their different spheres of application.<br></div><div><br></div></div=
></div></blockquote><div><br></div><div>Understood.</div><div>=C2=A0</div><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div></div>Thanks,<br><=
/div>Maxim<br></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quot=
e"><div><div class=3D"h5">On Tue, Mar 28, 2017 at 1:17 AM, Jonathan Coe <sp=
an dir=3D"ltr"><<a href=3D"mailto:jonathanbcoe@gmail.com" target=3D"_bla=
nk">jonathanbcoe@gmail.com</a>></span> wrote:<br></div></div><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div><div class=3D"h5"><div dir=3D"ltr"><br><div class=
=3D"gmail_extra"><br><div class=3D"gmail_quote"><div><div class=3D"m_725712=
8278707438232h5">On 27 March 2017 at 18:10, Maxim Yanchenko <span dir=3D"lt=
r"><<a href=3D"mailto:maxim.yanchenko@gmail.com" target=3D"_blank">maxim=
..yanchenko@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"=
ltr"><div><div><div><div><div><div>Good day to everyone,<br><br>I checked t=
he existing proposals regarding <span style=3D"font-family:monospace,monosp=
ace">array_view</span> (including the multi-dimensional and strided ones) a=
nd I found none that would support byte stride (please correct me if I miss=
ed one, apologies in advance).<br></div>I have my own custom array view wri=
tten long time ago which I use a lot and found it extremely convenient, and=
it differs from the proposed <span style=3D"font-family:monospace,monospac=
e">array_view</span> by having an additional runtime parameter <span style=
=3D"font-family:monospace,monospace">byte_stride</span> (defaulted to <span=
style=3D"font-family:monospace,monospace">sizeof(T)</span> to have usual <=
span style=3D"font-family:monospace,monospace">array_view</span> by default=
).<br></div>The <span style=3D"font-family:monospace,monospace">byte_stride=
</span> is not part of the type, so the type is still the same <span style=
=3D"font-family:monospace,monospace">array_view<class T, int Rank=3D1>=
;</span><span style=3D"font-family:arial,helvetica,sans-serif"> and</span> =
you can use it for both contiguous arrays and <span style=3D"font-family:ar=
ial,helvetica,sans-serif">byte-strided </span>arrays.<br><br></div><div>So =
the constructor looks like this (for 1D array view): <br></div><div><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">ar=
ray_view( T* ptr, size_t size, size_t byte_stride =3D sizeof(T) );</span><b=
r></div><br></div><div><b>Motivation</b><br></div><div>In scientific/financ=
ial calculations one often has arrays of sets of parameters, i.e. arrays of=
structs:<br></div><div style=3D"margin-left:40px"><span style=3D"font-fami=
ly:monospace,monospace">struct BasicData {<br></span></div><div style=3D"ma=
rgin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 int =
data1;<br></span></div><div style=3D"margin-left:40px"><span style=3D"font-=
family:monospace,monospace">=C2=A0 int data2;<br></span></div><div style=3D=
"margin-left:40px"><span style=3D"font-family:monospace,monospace">};<br></=
span><span style=3D"font-family:monospace,monospace"><span style=3D"font-fa=
mily:monospace,monospace">BasicData </span>barr[50]; </span></div><div>It&#=
39;s also not unusual to have extended versions of algorithms that use addi=
tional parameters on top of the generic ones (or save additional data on to=
p of the common one).<br></div><div>The natural way of dealing with this is=
just inheriting from the basic struct and make an array of the derived str=
uct:<br></div><div style=3D"margin-left:40px"><span style=3D"font-family:mo=
nospace,monospace">struct </span><span style=3D"font-family:monospace,monos=
pace"><span style=3D"font-family:monospace,monospace">ExtendedData </span><=
span style=3D"font-family:arial,helvetica,sans-serif"></span>: </span><span=
style=3D"font-family:monospace,monospace"><span style=3D"font-family:monos=
pace,monospace">BasicData </span>{<br></span></div><div style=3D"margin-lef=
t:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 int data3;<b=
r></span></div><div><div style=3D"margin-left:40px"><span style=3D"font-fam=
ily:monospace,monospace">};<br></span><span style=3D"font-family:monospace,=
monospace"><span style=3D"font-family:monospace,monospace"><span style=3D"f=
ont-family:monospace,monospace">ExtendedData e</span></span>arr[50];</span>=
<br></div> this way you can access common and extended data the same way=20
without changing your code (and you can freely move parameters from=20
derived struct to the base and back, without affecting the specialized=20
code that uses them):<br></div><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace">earr.data1[i] =3D earr.data2[i] * earr=
..data3[i];<br><br></span></div><div>The problem here is that now even the c=
ode that doesn't need extended data (like ones gathering common statist=
ics or statuses) and would happily run on just basic data (and therefore co=
uld have been factored out to the common unspecialized codebase)<br><div st=
yle=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">vo=
id common_processing(array_view<</span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace">B<wbr>asicDa=
ta</span>>);</span><br></div>Such a function can't run because there=
is no array of basic params anymore, they are hidden inside the bigger ext=
ended params struct, and there is currently no way to get an <span style=3D=
"font-family:monospace,monospace">array_view<BasicData></span> out of=
<span style=3D"font-family:monospace,monospace">earr</span>.<br></div><div=
>Strided array_view won't help because <span style=3D"font-family:monos=
pace,monospace">sizeof(BasicData) </span><span style=3D"font-family:arial,h=
elvetica,sans-serif">is </span><span style=3D"font-family:monospace,monospa=
ce">2*sizeof(int), while sizeof(</span><span style=3D"font-family:monospace=
,monospace">ExtendedData</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"></span><span style=3D"font-family:monospace,monospace">) </span>=
<span style=3D"font-family:arial,helvetica,sans-serif">is </span><span styl=
e=3D"font-family:monospace,monospace">3*sizeof(int)</span><span style=3D"fo=
nt-family:arial,helvetica,sans-serif"> - so strides of </span><span style=
=3D"font-family:monospace,monospace">sizeof(</span><span style=3D"font-fami=
ly:monospace,monospace">BasicData</span><span style=3D"font-family:monospac=
e,monospace">)</span><span style=3D"font-family:arial,helvetica,sans-serif"=
> won't work.</span><span style=3D"font-family:monospace,monospace"><br=
></span></div><div><br></div><div>Also, there can be a plugin-like architec=
ture of the program so the host wouldn't even know the type <span style=
=3D"font-family:monospace,monospace">ExtendedData </span><span style=3D"fon=
t-family:arial,helvetica,sans-serif"></span><span style=3D"font-family:aria=
l,helvetica,sans-serif">that exists only in the plugin but still could acce=
ss</span><span style=3D"font-family:monospace,monospace"> </span><span styl=
e=3D"font-family:monospace,monospace">BasicData </span><span style=3D"font-=
family:arial,helvetica,sans-serif">owned by the plugin if there was a way t=
o construct </span><br><span style=3D"font-family:monospace,monospace">arra=
y_view<</span><span style=3D"font-family:monospace,monospace"><span styl=
e=3D"font-family:monospace,monospace">BasicData</span>>.</span></div><di=
v><br>All the above is easily achievable with <span style=3D"font-family:ar=
ial,helvetica,sans-serif">a byte-strided </span><span style=3D"font-family:=
monospace,monospace">array_view</span>.<br><br><br></div><div>Another examp=
le: think of <span style=3D"font-family:monospace,monospace">BasicData </sp=
an>as<span style=3D"font-family:monospace,monospace"> RGB </span>and <span =
style=3D"font-family:monospace,monospace">ExtendedData </span><span style=
=3D"font-family:arial,helvetica,sans-serif">as<span style=3D"font-family:mo=
nospace,monospace"> </span></span><span style=3D"font-family:monospace,mono=
space">RGBA/ARGB:</span> you could have an <span style=3D"font-family:monos=
pace,monospace">array_view<RGB></span> over an RGBA file and an RGB f=
ile and even an ARGB file, agnostically - they will only differ in their <s=
pan style=3D"font-family:monospace,monospace">byte_stride</span> value.<br>=
<br><br></div><div><br></div>Here are the use cases (1D, for simplicity):<b=
r><br></div><div><b>1) Use as a normal <span style=3D"font-family:monospace=
,monospace">array_view</span>:</b><br></div><div style=3D"margin-left:40px"=
><span style=3D"font-family:monospace,monospace"><span style=3D"font-family=
:monospace,monospace">struct B {<br></span><span style=3D"font-family:monos=
pace,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monosp=
ace,monospace">};<br></span></span><span style=3D"font-family:monospace,mon=
ospace">B *pb =3D new B[50];</span></div><div><div style=3D"margin-left:40p=
x"><span style=3D"font-family:monospace,monospace">array_view<B> av( =
pb, 50 ); // byte_stride</span><span style=3D"font-family:arial,helvetica,s=
ans-serif"> is defaulted to</span><span style=3D"font-family:monospace,mono=
space"> sizeof(B)</span><br></div><div style=3D"margin-left:40px"><span sty=
le=3D"font-family:monospace,monospace"></span></div><span style=3D"font-fam=
ily:monospace,monospace"><br></span></div><b>2) view of an array of a deriv=
ed class D as an array of base class B:</b><br></div><span style=3D"font-fa=
mily:monospace,monospace"></span></div><div style=3D"margin-left:40px"><spa=
n style=3D"font-family:monospace,monospace"><span style=3D"font-family:mono=
space,monospace"><span style=3D"font-family:monospace,monospace">struct B {=
<br></span><span style=3D"font-family:monospace,monospace">=C2=A0 int x,y;<=
br></span><span style=3D"font-family:monospace,monospace">};<br></span></sp=
an><span style=3D"font-family:monospace,monospace"></span>struct D: B {<br>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">=C2=A0 int a;<br>};<br></span></div><div style=3D"margin-=
left:40px"><span style=3D"font-family:monospace,monospace">D *pd =3D new D[=
50];<br></span></div><div><div style=3D"margin-left:40px"><span style=3D"fo=
nt-family:monospace,monospace">array_view<B> av_b( pd, 50, sizeof(D) =
);<br><br></span><span style=3D"font-family:monospace,monospace"></span></d=
iv><span style=3D"font-family:arial,helvetica,sans-serif">(</span><span sty=
le=3D"font-family:monospace,monospace">pd </span><span style=3D"font-family=
:arial,helvetica,sans-serif">automatically converted to </span><span style=
=3D"font-family:monospace,monospace">B*, sizeof(B) =3D=3D 2*sizeof(int), si=
zeof(D) =3D=3D 3*sizeof(int)</span><span style=3D"font-family:arial,helveti=
ca,sans-serif"> so usual integer stride won't work here because <span s=
tyle=3D"font-family:monospace,monospace">sizeof(D)</span> is not a multiple=
of <span style=3D"font-family:monospace,monospace">sizeof(B)</span>)</span=
><br><br></div><div>to avoid mistakes, an obvious helper function <span sty=
le=3D"font-family:monospace,monospace">array_view_by_base()</span> is provi=
ded (it also checks <span style=3D"font-family:monospace,monospace">static_=
assert(std::is_base_of_<wbr>v<B,D>)</span>):<br></div><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">array_view=
<B> av_b =3D array_view_by_base<B>( pd, 50 );</span></div><div>=
<br></div><div><b>3) Member view ("array" of field b):</b><br><di=
v style=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace=
"><span style=3D"font-family:monospace,monospace"><span style=3D"font-famil=
y:monospace,monospace">struct B {<br></span><span style=3D"font-family:mono=
space,monospace">=C2=A0 int x,y;<br></span><span style=3D"font-family:monos=
pace,monospace">};<br></span></span><span style=3D"font-family:monospace,mo=
nospace"></span>struct C {<br></span></div><div style=3D"margin-left:40px">=
<span style=3D"font-family:monospace,monospace">=C2=A0 int a;</span><br><sp=
an style=3D"font-family:monospace,monospace"></span></div></div><div style=
=3D"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=
=A0 B b;<br></span></div><div style=3D"margin-left:40px"><span style=3D"fon=
t-family:monospace,monospace">};</span><span style=3D"font-family:monospace=
,monospace"><br></span><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">C *pc =3D new C[50];<br></span>=
</span></div><div style=3D"margin-left:40px"><span style=3D"font-family:mon=
ospace,monospace">array_view<B>=C2=A0=C2=A0 av_b( </span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">&pc[0].b,=C2=A0=C2=A0 50, sizeof(C) </span>);<br></span></div=
><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,monos=
pace">array_view<int> av_y( </span><span style=3D"font-family:monospa=
ce,monospace"><span style=3D"font-family:monospace,monospace">&pc[0].b.=
y, 50, sizeof(C) </span>);<br></span></div><span style=3D"font-family:monos=
pace,monospace"></span><span style=3D"font-family:monospace,monospace"><fon=
t face=3D"arial,helvetica,sans-serif"><br>Again, to avoid mistakes, a helpe=
r function </font>array_view_by_member()</span><span style=3D"font-family:a=
rial,helvetica,sans-serif"> is provided</span>:<br><span style=3D"font-fami=
ly:monospace,monospace"></span><div style=3D"margin-left:40px"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view<B>=C2=A0=C2=A0 av_b =3D array_view_by_member( pc=
, &C::b, 50 );</span></span> // both D and B are deduced from the argum=
ents<br><br></div><div>Unfortunately, there is currently no way in C++ to h=
ave a nested pointer-to-member so it's impossible to write something li=
ke <span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace">&C::b::y</span></span><span style=3D"font-famil=
y:arial,helvetica,sans-serif">. This can be emulated, to some extent, by pr=
oviding a tuple like <span style=3D"font-family:monospace,monospace">(&=
C::b, &B::y)</span> but it's not much more readable than the unsafe=
version. So the safe version for <span style=3D"font-family:'times new=
roman',serif">av_y</span> would be</span><span style=3D"font-family:&#=
39;times new roman',serif">:</span><span style=3D"font-family:monospace=
,monospace"><span style=3D"font-family:monospace,monospace"><br></span></sp=
an><div style=3D"margin-left:40px"><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace">array_view<int&g=
t; av_y =3D array_view_by_member( pc, std::make_tuple(&C::b,</span></sp=
an><span style=3D"font-family:monospace,monospace"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:arial,helvetica,sans-ser=
if"><span style=3D"font-family:monospace,monospace"> &B::y)</span></spa=
n>, 50 );</span></span> // both D and int are deduced from the arguments</d=
iv></div><div><br></div><div><b>4) Strided views for all the cases above</b=
>:<br></div><div>Just call the constructor with stride*sizeof(D) instead of=
just sizeof(D)<br></div><div><br><br></div><div><b>Note 1:</b> when the ar=
gument p above is not a plain pointer but a container that knows its size (=
via std::size - think of std::vector, std::array, or even another array_vie=
w) then you don't need to provide the size manually:<br><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">std::vecto=
r<B> vb;</span><br><span style=3D"font-family:monospace,monospace">ar=
ray_view<B> av_b( vb );</span><br><span style=3D"font-family:monospac=
e,monospace">std::vector<D> vd;</span><br><span style=3D"font-family:=
monospace,monospace"><span style=3D"font-family:monospace,monospace"><span =
style=3D"font-family:monospace,monospace"><span style=3D"font-family:monosp=
ace,monospace">array_view<B> av_b =3D </span>array_view_by_base<B&=
gt;( vd );</span></span></span><br><span style=3D"font-family:monospace,mon=
ospace"><span style=3D"font-family:monospace,monospace"><span style=3D"font=
-family:monospace,monospace"></span></span></span><span style=3D"font-famil=
y:monospace,monospace"><span style=3D"font-family:monospace,monospace"><spa=
n style=3D"font-family:monospace,monospace">std::vector<C> vc;</span>=
<br><span style=3D"font-family:monospace,monospace"><span style=3D"font-fam=
ily:monospace,monospace"><span style=3D"font-family:monospace,monospace"><s=
pan style=3D"font-family:monospace,monospace"></span></span></span></span>a=
rray_view<B> av_b =3D </span></span><span style=3D"font-family:monosp=
ace,monospace"><span style=3D"font-family:monospace,monospace"><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace">array_view_by_member</span></span></span>( vc</span><span style=
=3D"font-family:monospace,monospace"><span style=3D"font-family:monospace,m=
onospace"><span style=3D"font-family:monospace,monospace">, &C::b</span=
></span> );</span><br></div><div style=3D"margin-left:40px"><span style=3D"=
font-family:monospace,monospace"></span></div><span style=3D"font-family:mo=
nospace,monospace"><br></span></div><div><span style=3D"font-family:arial,h=
elvetica,sans-serif"><b>Note 2:</b> advantage over some other proposals is =
in the uniform type <span style=3D"font-family:monospace,monospace">array_v=
iew<T,Rank></span> that doesn't depend on the "continuousnes=
s" (unlike n4177 where strided view is a separate type </span><span st=
yle=3D"font-family:arial,helvetica,sans-serif"><code>strided_array_view</co=
de>). <br>For those who need to know if the view is contiguous (for example=
, to do a bulk <span style=3D"font-family:monospace,monospace">memcpy</span=
> instead of element-wise copying) there is a member function=C2=A0 <span s=
tyle=3D"font-family:monospace,monospace">bool continuous() const</span> pro=
vided that just checks if <span style=3D"font-family:monospace,monospace">s=
izeof(T)=3D=3Dbyte_stride</span>.<br></span><span style=3D"font-family:aria=
l,helvetica,sans-serif"><br></span></div><div><span style=3D"font-family:ar=
ial,helvetica,sans-serif"><b>Note 3:</b> array_view supports default constr=
uction and assignment (this is necessary for the cases when we have a view =
in the host program, then we load a plugin, attach to its memory, and initi=
alized our array_view to look at the plugin's memory, and then we can u=
nload the plugin and load another, with a different derived type, and reini=
tialized our array_view again).<br><br></span></div><div><span style=3D"fon=
t-family:arial,helvetica,sans-serif"><br></span></div><div><span style=3D"f=
ont-family:arial,helvetica,sans-serif">Comments?<br>If there is </span><spa=
n style=3D"font-family:arial,helvetica,sans-serif"><span style=3D"font-fami=
ly:monospace,monospace"><span style=3D"font-family:monospace,monospace"></s=
pan></span></span>an agreement that it would be good to have (from my exper=
ience, it is) I'll write a formal proposal.<br><br></div></div></blockq=
uote><div><br></div></div></div><div><span style=3D"font-size:12.8000001907=
34863px;font-family:arial,helvetica,sans-serif">A byte-strided=C2=A0</span>=
<span style=3D"font-size:12.800000190734863px;font-family:monospace,monospa=
ce">array_view would lose many of the advantages of memory contiguity. I=
9;d be inclined to use a struct of array_views rather than a strided array =
view of structs.</span><br></div><div>=C2=A0</div><div><div><div style=3D"m=
argin-left:40px"><span style=3D"font-family:monospace,monospace">struct C_v=
iew {<br></span></div><div style=3D"margin-left:40px"><span style=3D"font-f=
amily:monospace,monospace">=C2=A0 array_view<int> as;</span><br><span=
style=3D"font-family:monospace,monospace"></span></div></div><div style=3D=
"margin-left:40px"><span style=3D"font-family:monospace,monospace">=C2=A0 a=
rray_view<B> bs;</span></div><div style=3D"margin-left:40px"><span st=
yle=3D"font-family:monospace,monospace">};</span></div></div><div><br></div=
><div>I think there are already some proposals in flight to convert vectors=
of structs into structs of vectors.</div><div><br></div><div>Regards,</div=
><div><br></div><div>Jon</div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col=
or:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span><div di=
r=3D"ltr"><div></div><div>Thanks everyone,<br></div><div>Yours sincerely,<b=
r></div><div>Maxim Yanchenko<span class=3D"m_7257128278707438232m_-32731970=
37045350056gmail-HOEnZb"><font color=3D"#888888"><br></font></span></div><s=
pan class=3D"m_7257128278707438232m_-3273197037045350056gmail-HOEnZb"><font=
color=3D"#888888"><div><span style=3D"font-family:monospace,monospace"><br=
></span></div></font></span></div></span><span class=3D"m_72571282787074382=
32HOEnZb"><font color=3D"#888888"><span class=3D"m_7257128278707438232m_-32=
73197037045350056gmail-HOEnZb"><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG9N6X_Q%3=
Dg5Umvmd78GXfDG2K2xw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter" target=3D"_blank">https://groups.google.com/a/is<wbr>ocpp.org/d/msgi=
d/std-proposals<wbr>/CA%2B6mTDf_%2BdxPnZBjLUKgWnEG<wbr>9N6X_Q%3Dg5Umvmd78GX=
fDG2K2xw%4<wbr>0mail.gmail.com</a>.<br>
</font></span></font></span></blockquote></div><span class=3D"m_72571282787=
07438232HOEnZb"><font color=3D"#888888"><br></font></span></div></div></div=
></div><span class=3D"m_7257128278707438232HOEnZb"><font color=3D"#888888">=
<div><div class=3D"h5">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></div></div>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE7caKWHPC=
zKjXWasOiuj-Hq7w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r" target=3D"_blank">https://groups.google.com/a/is<wbr>ocpp.org/d/msgid/st=
d-proposals<wbr>/CAAbBDD9_iSMBN%2Bx4tHXZoQKoqE<wbr>7caKWHPCzKjXWasOiuj-Hq7w=
%<wbr>40mail.gmail.com</a>.<br>
</font></span></blockquote></div><br></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2B6mTDfFFdptzZSdLf98_ph_g%2B_M%3Dt=
9gAWT8a865W4jjYq5s%2Bw%40mail.gmail.com?utm_medium=3Demail&utm_source=
=3Dfooter" target=3D"_blank">https://groups.google.com/a/<wbr>isocpp.org/d/=
msgid/std-<wbr>proposals/CA%<wbr>2B6mTDfFFdptzZSdLf98_ph_g%2B_<wbr>M%3Dt9gA=
WT8a865W4jjYq5s%2Bw%<wbr>40mail.gmail.com</a>.<br>
</blockquote></div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAAbBDD_Jg90vddVRwkRpDEaegUGk4Xx9oi-F=
fK7Js_Ky0o0Dug%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAAbBDD_Jg90vddVR=
wkRpDEaegUGk4Xx9oi-FfK7Js_Ky0o0Dug%40mail.gmail.com</a>.<br />
--001a114125fe036db7054bb9cf80--
.