Topic: Implicitly cast-able enum range view


Author: mattphillips@mail.com
Date: Mon, 20 Mar 2017 04:54:59 -0700 (PDT)
Raw View
------=_Part_5672_817959847.1490010899976
Content-Type: multipart/alternative;
 boundary="----=_Part_5673_684024710.1490010899977"

------=_Part_5673_684024710.1490010899977
Content-Type: text/plain; charset=UTF-8

Consider this problem:

public:
enum class State
{
Pending,
Processing,
Completed
};

State GetState() const;
void SetState(State state) const;

private:
enum class StateInternal
{
Pending,
Processing,
Completed,
Garbage,
Error
};

StateInternal m_state;

The public interface defines a subset of the object's state enum to be read
and written, hiding any values that are invalid/confusing in any external
context.

The problem is that the enums must either be order maintained (for
casting), or involve branching to convert from one to another.

My proposed solution is a method of defining a "view" of an enum's range:

public:
enum view State : StateInternal<Pending, Completed>;

State GetState() const;
void SetState(State state) const;

private:
enum class StateInternal
{
Pending,
Processing,
Completed,
Garbage,
Error
};

The view of the enum (State) can be implicitly cast to/from its base
(StateInternal), allowing for subsets of the enum to be provided to
external-facing APIs only with values relevant to the context.

It could extend beyond a simple range; perhaps a way to cherry-pick valid
values from the base.


Disclaimer: I wouldn't consider myself completely C++ fluent, so the
terminology and/or syntax might not be the best. Please let me know if
you'd like further examples.

--
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/ead976bc-527a-4bfd-9d1c-bd20fad9166a%40isocpp.org.

------=_Part_5673_684024710.1490010899977
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Consider this problem:<div><br></div><div><div class=3D"pr=
ettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-w=
ord;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><div class=
=3D"subprettyprint"><font color=3D"#660066"><div class=3D"subprettyprint">p=
ublic:</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" st=
yle=3D"white-space:pre"> </span>enum class State</div><div class=3D"subpret=
typrint"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>{=
</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D=
"white-space:pre">  </span>Pending,</div><div class=3D"subprettyprint"><spa=
n class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>Processing,</=
div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D"w=
hite-space:pre">  </span>Completed</div><div class=3D"subprettyprint"><span=
 class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>};</div><div cl=
ass=3D"subprettyprint"><br></div><div class=3D"subprettyprint"><span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>State GetState() cons=
t;</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=
=3D"white-space:pre"> </span>void SetState(State state) const;</div><div cl=
ass=3D"subprettyprint"><br></div><div class=3D"subprettyprint">private:</di=
v><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D"whi=
te-space:pre"> </span>enum class StateInternal</div><div class=3D"subpretty=
print"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>{</=
div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D"w=
hite-space:pre">  </span>Pending,</div><div class=3D"subprettyprint"><span =
class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>Processing,</di=
v><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D"whi=
te-space:pre">  </span>Completed,</div><div class=3D"subprettyprint"><span =
class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>Garbage,</div><=
div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D"white-=
space:pre">  </span>Error</div><div class=3D"subprettyprint"><span class=3D=
"Apple-tab-span" style=3D"white-space:pre"> </span>};</div><div class=3D"su=
bprettyprint"><br></div><div class=3D"subprettyprint"><span class=3D"Apple-=
tab-span" style=3D"white-space:pre"> </span>StateInternal m_state;</div></f=
ont></div></div></code></div><br>The public interface defines a subset of t=
he object&#39;s state enum to be read and written, hiding any values that a=
re invalid/confusing in any external context.</div><div><br></div><div>The =
problem is that the enums must either be order maintained (for casting), or=
 involve branching to convert from one to another.</div><div><br></div><div=
>My proposed solution is a method of defining a &quot;view&quot; of an enum=
&#39;s range:</div><div><br></div><div><div class=3D"prettyprint" style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><font color=3D"#660066"><div cl=
ass=3D"subprettyprint">public:</div><div class=3D"subprettyprint"><span cla=
ss=3D"Apple-tab-span" style=3D"white-space:pre"> </span>enum view State : S=
tateInternal&lt;Pending, Completed&gt;;</div><div class=3D"subprettyprint">=
<br></div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" styl=
e=3D"white-space:pre"> </span>State GetState() const;</div><div class=3D"su=
bprettyprint"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </s=
pan>void SetState(State state) const;</div><div class=3D"subprettyprint"><b=
r></div><div class=3D"subprettyprint">private:</div><div class=3D"subpretty=
print"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>enu=
m class StateInternal</div><div class=3D"subprettyprint"><span class=3D"App=
le-tab-span" style=3D"white-space:pre"> </span>{</div><div class=3D"subpret=
typrint"><span class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>=
Pending,</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" =
style=3D"white-space:pre">  </span>Processing,</div><div class=3D"subpretty=
print"><span class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>Co=
mpleted,</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" =
style=3D"white-space:pre">  </span>Garbage,</div><div class=3D"subprettypri=
nt"><span class=3D"Apple-tab-span" style=3D"white-space:pre">  </span>Error=
</div><div class=3D"subprettyprint"><span class=3D"Apple-tab-span" style=3D=
"white-space:pre"> </span>};</div></font></div></code></div><br>The view of=
 the enum (State) can be implicitly cast to/from its base (StateInternal), =
allowing for subsets of the enum to be provided to external-facing APIs onl=
y with values relevant to the context.</div><div><br></div><div>It could ex=
tend beyond a simple range; perhaps a way to cherry-pick valid values from =
the base.</div><div><br></div><div><br></div><div>Disclaimer: I wouldn&#39;=
t consider myself completely C++ fluent, so the terminology and/or syntax m=
ight not be the best. Please let me know if you&#39;d like further examples=
..</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/ead976bc-527a-4bfd-9d1c-bd20fad9166a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ead976bc-527a-4bfd-9d1c-bd20fad9166a=
%40isocpp.org</a>.<br />

------=_Part_5673_684024710.1490010899977--

------=_Part_5672_817959847.1490010899976--

.


Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Fri, 24 Mar 2017 16:14:53 -0700 (PDT)
Raw View
------=_Part_1005_457585711.1490397293630
Content-Type: multipart/alternative;
 boundary="----=_Part_1006_287369413.1490397293630"

------=_Part_1006_287369413.1490397293630
Content-Type: text/plain; charset=UTF-8

On Monday, March 20, 2017 at 4:55:00 AM UTC-7, mattph...@mail.com wrote:
>
> The problem is that the enums must either be order maintained (for
> casting), or involve branching to convert from one to another.
>

I only skimmed, but the immediate problem with anything that looks or
smells like enum inheritance is slicing or up-converting. In your case, how
do you convert automatically from a StateInternal value to a public State
value? That's especially important in your example, since hypothetically
you want to store the internal value and just provide an accessor to the
public value.

I might suggest here that you actually don't _need_ the enums to be the
same. Your accessor can do this for you.

  enum class State { Pending, Completed };
  enum class StateInternal { Pending, Processing, Garbage, etc. };

  State getState() const { return (state == StateInternal::Pending ||
_state == StateInternal::Procising) ? State::Pending : Stte::Completed; }


Alternatively, this is also the kind of thing that sum types (aka
std::variant) are good for:

  struct PendingStates { enum { Pending, Processing } state; };
  struct CompletedStates { enum { Completed, Garbage, Error } state; };

  using State = std::variant<PendingStates, CompletedStates>;

Public consumers can query the variant to see when the item is pending or
completed, and can decompose the variant to get any internal state.

That of course looks an awful lot prettier in languages with native support
for sum types, so I personally would go for the first solution. :)

--
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/287d147c-0767-47f2-a986-af0d5613627b%40isocpp.org.

------=_Part_1006_287369413.1490397293630
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Monday, March 20, 2017 at 4:55:00 AM UTC-7, mattph...@m=
ail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div>The problem is that the enums must either be order maintained (for ca=
sting), or involve branching to convert from one to another.</div></div></b=
lockquote><div><br></div><div>I only skimmed, but the immediate problem wit=
h anything that looks or smells like enum inheritance is slicing or up-conv=
erting. In your case, how do you convert automatically from a StateInternal=
 value to a public State value? That&#39;s especially important in your exa=
mple, since hypothetically you want to store the internal value and just pr=
ovide an accessor to the public value.</div><div><br></div><div>I might sug=
gest here that you actually don&#39;t _need_ the enums to be the same. Your=
 accessor can do this for you.</div><div><br></div><div>=C2=A0 enum class S=
tate { Pending, Completed };</div><div>=C2=A0 enum class StateInternal { Pe=
nding, Processing, Garbage, etc. };</div><div><br></div><div>=C2=A0 State g=
etState() const { return (state =3D=3D StateInternal::Pending || _state =3D=
=3D StateInternal::Procising) ? State::Pending : Stte::Completed; }</div><d=
iv><br></div><div><br></div><div>Alternatively, this is also the kind of th=
ing that sum types (aka std::variant) are good for:</div><div><br></div><di=
v>=C2=A0 struct PendingStates { enum { Pending, Processing } state; };</div=
><div>=C2=A0 struct CompletedStates=C2=A0{ enum { Completed, Garbage, Error=
 } state; };</div><div><br></div><div>=C2=A0 using State =3D std::variant&l=
t;PendingStates, CompletedStates&gt;;</div><div><br></div><div>Public consu=
mers can query the variant to see when the item is pending or completed, an=
d can decompose the variant to get any internal state.</div><div><br></div>=
<div>That of course looks an awful lot prettier in languages with native su=
pport for sum types, so I personally would go for the first solution. :)</d=
iv></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/287d147c-0767-47f2-a986-af0d5613627b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/287d147c-0767-47f2-a986-af0d5613627b=
%40isocpp.org</a>.<br />

------=_Part_1006_287369413.1490397293630--

------=_Part_1005_457585711.1490397293630--

.


Author: mattphillips@mail.com
Date: Fri, 24 Mar 2017 16:58:12 -0700 (PDT)
Raw View
------=_Part_1314_1391626127.1490399892521
Content-Type: multipart/alternative;
 boundary="----=_Part_1315_836127674.1490399892521"

------=_Part_1315_836127674.1490399892521
Content-Type: text/plain; charset=UTF-8

No, my proposal isn't for enum inheritance, it's for restricting access (or
providing a "view of") specified enum values for different contexts,
without the need for branching or manual conversions requiring maintenance
of two disparate but related enums.

On Friday, 24 March 2017 23:14:53 UTC, Sean Middleditch wrote:
>
> On Monday, March 20, 2017 at 4:55:00 AM UTC-7, mattph...@mail.com wrote:
>>
>> The problem is that the enums must either be order maintained (for
>> casting), or involve branching to convert from one to another.
>>
>
> I only skimmed, but the immediate problem with anything that looks or
> smells like enum inheritance is slicing or up-converting. In your case, how
> do you convert automatically from a StateInternal value to a public State
> value? That's especially important in your example, since hypothetically
> you want to store the internal value and just provide an accessor to the
> public value.
>
> I might suggest here that you actually don't _need_ the enums to be the
> same. Your accessor can do this for you.
>
>   enum class State { Pending, Completed };
>   enum class StateInternal { Pending, Processing, Garbage, etc. };
>
>   State getState() const { return (state == StateInternal::Pending ||
> _state == StateInternal::Procising) ? State::Pending : Stte::Completed; }
>
>
> Alternatively, this is also the kind of thing that sum types (aka
> std::variant) are good for:
>
>   struct PendingStates { enum { Pending, Processing } state; };
>   struct CompletedStates { enum { Completed, Garbage, Error } state; };
>
>   using State = std::variant<PendingStates, CompletedStates>;
>
> Public consumers can query the variant to see when the item is pending or
> completed, and can decompose the variant to get any internal state.
>
> That of course looks an awful lot prettier in languages with native
> support for sum types, so I personally would go for the first solution. :)
>

--
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/cf5e3d99-2838-4c5f-8408-b8316cda53fd%40isocpp.org.

------=_Part_1315_836127674.1490399892521
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">No, my proposal isn&#39;t for enum inheritance, it&#39;s f=
or restricting access (or providing a &quot;view of&quot;) specified enum v=
alues for different contexts, without the need for branching or manual conv=
ersions requiring maintenance of two disparate but related enums.<br><br>On=
 Friday, 24 March 2017 23:14:53 UTC, Sean Middleditch  wrote:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Monday, March 20, 2017 a=
t 4:55:00 AM UTC-7, <a>mattph...@mail.com</a> wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>The problem is that the enums must e=
ither be order maintained (for casting), or involve branching to convert fr=
om one to another.</div></div></blockquote><div><br></div><div>I only skimm=
ed, but the immediate problem with anything that looks or smells like enum =
inheritance is slicing or up-converting. In your case, how do you convert a=
utomatically from a StateInternal value to a public State value? That&#39;s=
 especially important in your example, since hypothetically you want to sto=
re the internal value and just provide an accessor to the public value.</di=
v><div><br></div><div>I might suggest here that you actually don&#39;t _nee=
d_ the enums to be the same. Your accessor can do this for you.</div><div><=
br></div><div>=C2=A0 enum class State { Pending, Completed };</div><div>=C2=
=A0 enum class StateInternal { Pending, Processing, Garbage, etc. };</div><=
div><br></div><div>=C2=A0 State getState() const { return (state =3D=3D Sta=
teInternal::Pending || _state =3D=3D StateInternal::Procising) ? State::Pen=
ding : Stte::Completed; }</div><div><br></div><div><br></div><div>Alternati=
vely, this is also the kind of thing that sum types (aka std::variant) are =
good for:</div><div><br></div><div>=C2=A0 struct PendingStates { enum { Pen=
ding, Processing } state; };</div><div>=C2=A0 struct CompletedStates=C2=A0{=
 enum { Completed, Garbage, Error } state; };</div><div><br></div><div>=C2=
=A0 using State =3D std::variant&lt;PendingStates, CompletedStates&gt;;</di=
v><div><br></div><div>Public consumers can query the variant to see when th=
e item is pending or completed, and can decompose the variant to get any in=
ternal state.</div><div><br></div><div>That of course looks an awful lot pr=
ettier in languages with native support for sum types, so I personally woul=
d go for the first solution. :)</div></div></blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/cf5e3d99-2838-4c5f-8408-b8316cda53fd%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cf5e3d99-2838-4c5f-8408-b8316cda53fd=
%40isocpp.org</a>.<br />

------=_Part_1315_836127674.1490399892521--

------=_Part_1314_1391626127.1490399892521--

.