220 30457 <a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: m.cencora@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: enum_cast proposal
Date: Tue, 10 Jan 2017 07:31:07 -0800 (PST)
Lines: 530
Approved: news@gmane.org
Message-ID: <a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd@isocpp.org>
References: <efdf2357-00a6-408a-8772-12f99135a880@isocpp.org>
 <57258435-5d82-48e7-8ed7-3c38682418fb@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_1640_282778673.1484062268061"
X-Trace: blaine.gmane.org 1484062284 17202 195.159.176.226 (10 Jan 2017 15:31:24 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 10 Jan 2017 15:31:24 +0000 (UTC)
Cc: m.cencora@gmail.com, gmisocpp@gmail.com
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBD7YFUMJRYMBBPH42PBQKGQE6X5VLVA@isocpp.org Tue Jan 10 16:31:17 2017
Return-path: <std-proposals+bncBD7YFUMJRYMBBPH42PBQKGQE6X5VLVA@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yw0-f200.google.com ([209.85.161.200])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBD7YFUMJRYMBBPH42PBQKGQE6X5VLVA@isocpp.org>)
	id 1cQyO9-00035m-Ab
	for gclcip-std-proposals@m.gmane.org; Tue, 10 Jan 2017 16:31:05 +0100
Original-Received: by mail-yw0-f200.google.com with SMTP id q71sf117544894ywg.1
        for <gclcip-std-proposals@m.gmane.org>; Tue, 10 Jan 2017 07:31:10 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=2zC9atiLjcqoLBIGtYwMbuYsymPNVopdgVbN7NtGR2E=;
        b=YiBuXcnjGcWp/8XfB1T5gQRvZhUH6mfpeSFfIH6XdoygLucBFT1TUW+jIkIO/gJfzF
         2BR59+XGZt9/Oqu4Ql87qE7dh4ADDD7qVZSF5voMCTIYKs7hB+MOUCObmRdkVboYU0u8
         v7ckxpNhP1q2XtTse5rgLT7wmr4RneIwkieGK+z0DTCiRKx6UW4D1gm/qTkL2/bki4Mk
         zil1FQ5mXKyKhgrDMn9Jogk9O5kos57My3WcCl2E691o6ht9645O/vEIdx5fe8/c6OBo
         KRbBwfy7x9K32v/L+UiTOtX+ux6jK1CaEl1ryHf7ftx2qnrOnTdqOd48XyD+VoCSnb0J
         9VXw==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:cc:message-id:in-reply-to:references:subject
         :mime-version:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=2zC9atiLjcqoLBIGtYwMbuYsymPNVopdgVbN7NtGR2E=;
        b=OWZmaEqIJEL5XWyqt3DVOn+Lxzh7RsMk/KAunCCiHsxaRNZUvMmeRc0Jrp0oirjG8e
         Zi0d0ZsU2HNDYLkGCU61CTq7bYyPIBChMofzERPoUw1D8JMiBGXmMDiezlPfuSvwzV5a
         Ps7AVXJPNnTVqgCNaiwuHse6GH6f/hEZapvxNi7wDvgXysbYIRDL01E3zXXNiloNjNva
         FjTs/NHH3W7/hcEce3MLtS6+Y6/Jy4b+4azOkqom22svqS8B1F4xwzQWm1ydpX6ClwI7
         nzNoeftOmZ9eROKNMm37fnLb66WCTne19GE7Fg3z7j5HysXeGLgi5SHZEcszdkhF1fk2
         V24w==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:cc:message-id:in-reply-to
         :references:subject:mime-version:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=2zC9atiLjcqoLBIGtYwMbuYsymPNVopdgVbN7NtGR2E=;
        b=P69G5inbyebKwzhS2eMZV3eWQcsNvz6AwSbJhHG/5i+Khb/SsTY42mI/gqKJLT42sO
         p0CD7/CIv8DTwn1KdQedeDaK4UqwqFQ8DMYoiwc2Rf7bQZhLrGYlrrjChrfRH0syrZ7j
         rhF7aEChNEnI+z1DByBL8VePpILPwNF0D7GqajSsT2d3N/AG5kKFAduNCqdB40pJPovz
         8Lw88qcAWUhQ5Hz2j+U6b/g1fdemtVvkgBPHjH5wcTMJekLgjmbEQWkGtRY6heGwR32Q
         vaw7Dg/gYACuTZR9iohLTlxszNxEn9jfS9McdNmr2IU4xrYdGhygKUzXviKnhIRGWUUi
         Ar0g==
X-Gm-Message-State: AIkVDXIyOoF/VCaHYJdL3VKy3Tz/J7rOuVRdefWQkC1SeWZyltd5p+vdKF7H3+bFeaCAqg==
X-Received: by 10.99.178.82 with SMTP id t18mr1243778pgo.45.1484062269540;
        Tue, 10 Jan 2017 07:31:09 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.41.177 with SMTP id n46ls1536569otb.37.gmail; Tue, 10 Jan
 2017 07:31:08 -0800 (PST)
X-Received: by 10.157.17.3 with SMTP id g3mr216919ote.8.1484062268522;
        Tue, 10 Jan 2017 07:31:08 -0800 (PST)
In-Reply-To: <57258435-5d82-48e7-8ed7-3c38682418fb@isocpp.org>
X-Original-Sender: m.cencora@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:30457
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/30457>

------=_Part_1640_282778673.1484062268061
Content-Type: multipart/alternative; 
	boundary="----=_Part_1641_1102541637.1484062268062"

------=_Part_1641_1102541637.1484062268062
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable


W dniu wtorek, 10 stycznia 2017 13:49:00 UTC+1 u=C5=BCytkownik gmis...@gmai=
l.com=20
napisa=C5=82:
>
>
>
> On Tuesday, January 3, 2017 at 10:56:05 PM UTC+13, m.ce...@gmail.com=20
> wrote:
>>
>> Hi,
>>
>> I propose to add a enum_cast function that safely casts int value to a=
=20
>> target enum type if int value represents a valid enumerator.
>>
>> template <typename Enum, typename Int>
>> optional<Enum> enum_cast(Int value);
>>
>> requires: is_enum<Enum>, is_integral<Int>
>>
>> enum color
>> {
>>    red =3D 1,
>>    green =3D 200,
>>    blue =3D 3
>> };
>>
>> static_assert(enum_cast<color>(200u) =3D=3D color::green);
>> static_assert(enum_cast<color>(3) =3D=3D color::blue);
>> static_assert(enum_cast<color>(4) =3D=3D nullopt);
>>
>>
>> This should work for both scoped and unscoped enums.
>> For opaque enums this would only check if value fits in underlying type.
>>
>> Why do we want this:
>>  - validation of input data (e.g. coming from user or deserialization).
>>  - other?
>>
>> I know this could be purely library extension if based on reflection, bu=
t=20
>> since we don't know when we will get reflection,
>> and implementation based on reflection may not be optimal,
>> I think it should be implemented with compiler support (i.e. via=20
>> __builtin_* intrinsic).
>>
>> Regards,
>> Maciej
>>
>
>
> I was thinking some more about this proposal. I really think the=20
> functionality you suggest is a good idea.
> I hope you proceed with a proposal. If you decide not to let me know.
>

I'll try to create a first draft after I get some more comments w.r.t to=20
exceptions.
For sure baseline API must be exception-free.
Do we really want to additionally support API that throws on error?
I'm rather inclined to leave it out - similarly as in to_chars/from_chars.
=20

>
> I hope this post assists you with your proposal. My suggestions are for=
=20
> your proposal to look something like this:
>
> In <utility> I think add:
>
> bool template<typename E, typename V> is_enum( V ev )
> {
>  // compiler magic:
>  // Calling this routine causes the compiler to generate or a call a=20
> routine
>  // that returns true if the value ev matches one of the enum E's
>  // values. otherwise false.
> }
>

'is_enum' name is already used in type_traits header.
Also is_enum seems redundant to me, since to_enum already reports
if convertion succeeded instead of:
if (is_enum<MyEnum>(139))

you could write:
if (to_enum<MyEnum>(139).is_valid)

or even:
if (to_enum<MyEnum>(139))
if we add explicit bool convertion operator for to_enum_result.



> // Users call this routine to convert an integer to an enum.
> They call this if they aren't sure about their conversion data
> // and don't mind exceptions and want simple like std::to_string
> // They might expect such a function to be present.
> // Though to be fair I'm not sure we should encourage this?
> // They should get good error messages.
> template<typename E, typename V> E to_enum_or_throw(V ev)
> {
>  if (is_enum<E>(ev))
>   return static_cast<E>(ev);
>  throw make_bad_enum<E,V>(ev);=20
> }
>
> template<typename E> class to_enum_result
> {
> public:
>  E enum_value;
>  bool is_valid;
> };
>
> // Call this if you can't use/afford exceptions. It seems optimal?
> template<typename E, typename V> to_enum_result<E> to_enum( V ev ) noexce=
pt
> {
>   if (is_enum<E, V>(ev))
>     return to_enum_result<E>{true,static_cast<E>(ev)};
>   return to_enum_result<E>{false, E{}};
> }
>
> // if is_valid returns false after to_enum, the user can use these=20
> routines to get good error
> // messages / report how they wish when they wish:
>

As there is only one possible reason why the to_enum failed
(integer didn't match any enumerator of target enumeration type)=20
I see no reason for following functions and classes.


> // Some type that holds the largest enum value ever possible.
> using std::any_enum_value =3D unspecified;
>
> class bad_enum
> {
> public:
>    std::any_any_enum_value bad_enum_value;
>    std::string enum_type_name;
> };
> =20
> template<typename E, typename V> std::bad_enum make_bad_enum(V ev)
> {
>  // Use some compiler magic to get the name of the name of the enum type =
E.
>  // Use it to construct a message like:
>  // '{ev}' is not a legal value for an enum of type '{E}'
>  return std::range_error(msg);
> }
>


>
> Note in all methods:
> * constrain E to only be an enum or enum class type.
> * constrain V to only accept integral types.
>
> Observations
> ------------
>
> * is_enum() is there for people who just need to check validity and no=20
> more.
> and saves the user writing redudant boiler plate code that the compiler=
=20
> does better.
> * to_enum_or_throw() is there for people who find simple works for them.
> its name makes it clear that exceptions can happen.
> * to_enum() is there for people who need performance and without=20
> exceptions.
>
=20

> * We don't depend on optional.=20
>
* Means <utility> isn't dependent on optional if we put it there.
> * make_bad_enum avoids making bad_enum a template.
> * make_bad_enum gives us good error messages and better than=20
> bad_optional_access.
> * make_bad_enum means we can create an error class for reporting elsewher=
e=20
> - we don't have to throw it.
> * make_bad_enum means we don't expose any get enum_type_name function the=
=20
> reflection people will reproduce.
> * make_bad_enum gives people flexibility to throw when they are ready=20
> instead of forcing a throw as soon as conversion fails.
> * Might play well with structured bindings.
> =20
>
Main choices:
> * We could model this on optional i.e. include has_value etc. but it seem=
s=20
> simpler not to. Either way is fine to me.
> I'm not sure such safety is warranted and from_chars/to_chars is pretty=
=20
> simple too so I went that way.
>

As committee already stated their preference in from_chars/to_chars case,=
=20
consider me convinced.
I will use 'to_enum_result' in draft.
Also I'll use 'to_enum' as function name to match 'to_chars' convention.
=20

> * The caller has all the utilities here to build that or work=20
> with optional directly - whatever they need.
> * I think being able to get good error messages on failure is important.
> This tries to enable making decent errors available no matter what method=
=20
> or is used.
>  i.e. include the enum type name and bad value in the error.=20
>
* I've used std::range_error as the exception type for failure but another=
=20
> may be appropriate.
> bad_enum as an exception type contains the value that was bad and the typ=
e=20
> name that it failed to convert to.
> This would allow people to extract the values to construct their own erro=
r=20
> messages (perhaps in other languages like French etc.).
>
> If std::bad_enum is too much API, that could be dropped for just=20
> std::range_error or something as long a it contains
> a full description of the error I think that's fine.
>

> I'd like to know what you and the Committee's disposition towards these=
=20
> ideas and views. Hope this helps.
>


Thanks for your valuable input.

Regards,
Maciej
=20

>
> Thanks
> GM
>

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd%40isocpp.or=
g.

------=_Part_1641_1102541637.1484062268062
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>W dniu wtorek, 10 stycznia 2017 13:49:00 UTC+1 u=C5=BC=
ytkownik gmis...@gmail.com napisa=C5=82:<blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><br><br>On Tuesday, January 3, 2017 at 10:56:05 =
PM UTC+13, <a>m.ce...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote"=
 style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(2=
04,204,204);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr"=
>Hi,<div><br></div><div>I propose to add a enum_cast function that safely c=
asts int value to a target enum type if int value represents a valid enumer=
ator.</div><div><br></div><div style=3D"border:1px solid rgb(187,187,187);b=
ackground-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,1=
36)">template</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(102,102,0)">&lt;</span><span style=3D"color:rgb(0,0,136)">typena=
me</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(=
102,0,102)">Enum</span><span style=3D"color:rgb(102,102,0)">,</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">typena=
me</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(=
102,0,102)">Int</span><span style=3D"color:rgb(102,102,0)">&gt;</span><span=
 style=3D"color:rgb(0,0,0)"><br>optional</span><span style=3D"color:rgb(102=
,102,0)">&lt;</span><span style=3D"color:rgb(102,0,102)">Enum</span><span s=
tyle=3D"color:rgb(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0,0)"> =
enum_cast</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D=
"color:rgb(102,0,102)">Int</span><span style=3D"color:rgb(0,0,0)"> value</s=
pan><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(=
0,0,0)"><br><br>requires</span><span style=3D"color:rgb(102,102,0)">:</span=
><span style=3D"color:rgb(0,0,0)"> is_enum</span><span style=3D"color:rgb(1=
02,102,0)">&lt;</span><font color=3D"#000000"><span style=3D"color:rgb(102,=
0,102)">Enum</span></font><span style=3D"color:rgb(102,102,0)">&gt;,</span>=
<span style=3D"color:rgb(0,0,0)"> is_integral</span><span style=3D"color:rg=
b(102,102,0)">&lt;</span><span style=3D"color:rgb(102,0,102)">Int</span><sp=
an style=3D"color:rgb(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0,0=
)"><br><br></span><span style=3D"color:rgb(0,0,136)">enum</span><span style=
=3D"color:rgb(0,0,0)"> color<br></span><span style=3D"color:rgb(102,102,0)"=
>{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0red </span><span=
 style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)">=
 </span><span style=3D"color:rgb(0,102,102)">1</span><span style=3D"color:r=
gb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0gr=
een </span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"co=
lor:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102)">200</span><spa=
n style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"><=
br>=C2=A0 =C2=A0blue </span><span style=3D"color:rgb(102,102,0)">=3D</span>=
<span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,102,102=
)">3</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color=
:rgb(102,102,0)">};</span><span style=3D"color:rgb(0,0,0)"><br><br></span><=
span style=3D"color:rgb(0,0,136)">static_assert</span><span style=3D"color:=
rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">enum_cast</span><s=
pan style=3D"color:rgb(0,136,0)">&lt;color&gt;</span><span style=3D"color:r=
gb(102,102,0)"><wbr>(</span><font color=3D"#006666"><span style=3D"color:rg=
b(0,102,102)">200u</span></font><span style=3D"color:rgb(102,102,0)">)</spa=
n><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102=
,0)">=3D=3D</span><span style=3D"color:rgb(0,0,0)"> color</span><span style=
=3D"color:rgb(102,102,0)">::</span><font color=3D"#000000"><span style=3D"c=
olor:rgb(0,0,0)">green</span></font><span style=3D"color:rgb(102,102,0)">);=
</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb=
(0,0,136)">static_assert</span><span style=3D"color:rgb(102,102,0)">(</span=
><span style=3D"color:rgb(0,0,0)">enum_cast</span><span style=3D"color:rgb(=
0,136,0)">&lt;color&gt;</span><span style=3D"color:rgb(102,102,0)"><wbr>(</=
span><span style=3D"color:rgb(0,102,102)">3</span><span style=3D"color:rgb(=
102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D=
"color:rgb(102,102,0)">=3D=3D</span><span style=3D"color:rgb(0,0,0)"> color=
</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:r=
gb(0,0,0)">blue</span><span style=3D"color:rgb(102,102,0)">);</span><span s=
tyle=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">sta=
tic_assert</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,0)">enum_cast</span><span style=3D"color:rgb(0,136,0)">&l=
t;color&gt;</span><span style=3D"color:rgb(102,102,0)"><wbr>(</span><span s=
tyle=3D"color:rgb(0,102,102)">4</span><span style=3D"color:rgb(102,102,0)">=
)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(1=
02,102,0)">=3D=3D</span><span style=3D"color:rgb(0,0,0)"> nullopt</span><sp=
an style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"=
><br><br></span></div></code></div><div><br></div><div>This should work for=
 both scoped and unscoped enums.</div><div>For opaque enums this would only=
 check if value fits in underlying type.<br></div><div><br></div><div>Why d=
o we want this:<br></div><div>=C2=A0- validation of input data (e.g. coming=
 from user or deserialization).</div><div>=C2=A0- other?</div><div><br></di=
v><div>I know this could be purely library extension if based on reflection=
, but since we don&#39;t know when we will get reflection,</div><div>and im=
plementation based on reflection may not be optimal,</div><div>I think it s=
hould be implemented with compiler support (i.e. via __builtin_* intrinsic)=
..</div><div><br></div><div>Regards,</div><div>Maciej</div></div></blockquot=
e><div><br></div><div><br></div><div>I was thinking some more about this pr=
oposal. I really think the functionality you suggest=C2=A0is a good idea.</=
div><div>I hope you proceed with a proposal.=C2=A0If you decide not to let =
me know.</div></div></blockquote><div><br></div><div>I&#39;ll try to create=
 a first draft after I get some more comments w.r.t to exceptions.</div><di=
v>For sure baseline API must be exception-free.</div><div>Do we really want=
 to additionally support API that throws on error?</div><div>I&#39;m rather=
 inclined to leave it out - similarly as in to_chars/from_chars.</div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>I hope this post assists you with your proposal.=C2=A0My=
 suggestions are for your proposal to look something like this:</div><div><=
br></div><div>In &lt;utility&gt; I think add:</div><div><br></div><div>bool=
 template&lt;typename E, typename V&gt; is_enum( V ev )</div><div>{</div><d=
iv>=C2=A0// compiler=C2=A0magic:</div><div>=C2=A0// Calling this routine ca=
uses the compiler to generate or a call a routine</div><div>=C2=A0// that r=
eturns true if the value ev matches one of the enum E&#39;s</div><div>=C2=
=A0// values. otherwise false.</div><div>}</div></div></blockquote><div><br=
></div><div>&#39;is_enum&#39; name is already used in type_traits header.<b=
r></div><div>Also is_enum seems redundant to me, since to_enum already repo=
rts</div><div>if convertion succeeded instead of:</div><div><div class=3D"p=
rettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break=
-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">is_enum</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span =
style=3D"color: #606;" class=3D"styled-by-prettify">MyEnum</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"=
color: #066;" class=3D"styled-by-prettify">139</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">))</span></div></code></div><br></div><=
div>you could write:</div><div><div class=3D"prettyprint" style=3D"border: =
1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(=
250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">to_enum</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">MyEnum</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;(</span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">139</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">).</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
is_valid</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)<=
/span></div></code></div><br></div><div>or even:</div><div><div class=3D"pr=
ettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-=
word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">to_enum</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">MyEnum</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;(</span><span style=3D"c=
olor: #066;" class=3D"styled-by-prettify">139</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">))</span></div></code></div>if we add ex=
plicit bool convertion operator for to_enum_result.</div><div><br></div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>// Users call this routine to convert an integer to an e=
num.</div><div>They call this if they=C2=A0aren&#39;t sure about=C2=A0their=
 conversion data</div><div>// and don&#39;t mind exceptions and want simple=
 like std::to_string</div><div>// They might expect such a function to be p=
resent.</div><div>// Though to be fair I&#39;m not sure we should encourage=
 this?</div><div>//=C2=A0They should get good error messages.</div><div>tem=
plate&lt;typename E, typename V&gt; E to_enum_or_throw(V ev)</div><div>{</d=
iv><div>=C2=A0if (is_enum&lt;E&gt;(ev))</div><div>=C2=A0=C2=A0return static=
_cast&lt;E&gt;(ev);</div><div>=C2=A0throw make_bad_enum&lt;E,V&gt;(ev);=C2=
=A0</div><div>}</div><div><br></div><div><div>template&lt;typename E&gt; cl=
ass to_enum_result</div><div>{</div><div>public:</div><div>=C2=A0E enum_val=
ue;</div><div>=C2=A0bool is_valid;</div><div>};</div><div><br></div></div><=
div>// Call this if you can&#39;t use/afford exceptions. It seems optimal?<=
/div><div>template&lt;typename E, typename V&gt; to_enum_result&lt;E&gt; to=
_enum( V ev ) noexcept</div><div>{</div><div>=C2=A0 if (is_enum&lt;E, V&gt;=
(ev))</div><div>=C2=A0=C2=A0=C2=A0 return to_enum_result&lt;E&gt;{true,stat=
ic_<wbr>cast&lt;E&gt;(ev)};</div><div>=C2=A0 return to_enum_result&lt;E&gt;=
{false, E{}};</div><div>}</div><div><br></div><div>// if is_valid=C2=A0retu=
rns false after to_enum, the user can use these routines to get good error<=
/div><div>// messages / report how they wish when they wish:</div></div></b=
lockquote><div><br></div><div>As there is only one possible reason why the =
to_enum failed<br></div><div>(integer didn&#39;t match any enumerator of ta=
rget enumeration type)=C2=A0</div><div>I see no reason for following functi=
ons and classes.</div><div><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
 1ex;"><div dir=3D"ltr"><div><br></div><div><div><div>// Some type that hol=
ds the largest enum value ever possible.</div><div><div>using std::any_enum=
_value =3D unspecified;</div><div><br></div></div></div><div>class bad_enum=
</div><div>{</div><div>public:</div><div>=C2=A0=C2=A0=C2=A0std::any_any_enu=
m_value bad_enum_value;</div><div>=C2=A0=C2=A0 std::string enum_type_name;<=
br>};</div><div>=C2=A0</div>template&lt;typename E, typename V&gt; std::bad=
_enum make_bad_enum(V ev)</div><div>{</div><div>=C2=A0// Use some compiler =
magic to get the name of the name of the=C2=A0enum type=C2=A0E.</div><div>=
=C2=A0// Use it to construct a message like:</div><div>=C2=A0// &#39;{ev}&#=
39; is not a legal value for an enum of type &#39;{E}&#39;</div><div>=C2=A0=
return std::range_error(msg);</div><div>}</div></div></blockquote><div><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><b=
r></div><div><br></div><div><div>Note in all methods:</div><div>* constrain=
 E to only be an enum or enum class type.</div><div>* constrain V to only a=
ccept integral types.</div><div><br></div></div><div>Observations</div><div=
>------------</div><div><br></div><div>* is_enum() is there for people who =
just need to check validity and no more.</div><div>and saves the user writi=
ng redudant boiler plate code that the compiler does better.</div><div>* to=
_enum_or_throw() is there for people who find simple works for them.</div><=
div>its name makes it clear that exceptions can happen.</div><div>* to_enum=
() is there for people who need performance and without exceptions.</div></=
div></blockquote><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div>* We don&#39;t depend on optional.=C2=A0</div><=
/div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><div>* Means &lt;utility&gt; isn&#39;t dependent on optional if we put=
 it there.</div><div><div>* make_bad_enum avoids making bad_enum a template=
..</div>* make_bad_enum gives us good error messages and better than bad_opt=
ional_access.</div><div>*=C2=A0make_bad_enum means=C2=A0we can=C2=A0create =
an=C2=A0error class=C2=A0for reporting elsewhere -=C2=A0we don&#39;t have t=
o throw it.</div><div>*=C2=A0make_bad_enum means we don&#39;t expose any ge=
t enum_type_name function the reflection people will reproduce.</div><div>*=
 make_bad_enum gives people flexibility to throw when they are ready instea=
d of forcing a throw as soon as conversion fails.</div><div>* Might play we=
ll with structured bindings.</div><div>=C2=A0<br></div></div></blockquote><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><di=
v>Main choices:</div><div>*=C2=A0We could=C2=A0model this on optional=C2=A0=
i.e. include=C2=A0has_value etc.=C2=A0but it=C2=A0seems simpler not to. Eit=
her way is fine to me.</div><div>I&#39;m not sure such safety is warranted =
and=C2=A0from_chars/to_chars is pretty simple too so I went that way.</div>=
</div></blockquote><div><br></div><div>As committee already stated their pr=
eference in from_chars/to_chars case, consider me convinced.</div><div>I wi=
ll use &#39;to_enum_result&#39; in draft.</div><div>Also I&#39;ll use &#39;=
to_enum&#39; as function name to match &#39;to_chars&#39; convention.</div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div>* The=C2=A0caller has all the utilities here to build that or=
 work with=C2=A0optional directly -=C2=A0whatever=C2=A0they need.</div><div=
>* I think=C2=A0being able to get=C2=A0good error messages on failure is im=
portant.</div><div>This tries to=C2=A0enable making decent errors available=
 no matter what method or=C2=A0is used.</div><div>=C2=A0i.e. include the en=
um type name and bad value in the error.=C2=A0</div></div></div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>* I&#3=
9;ve=C2=A0used std::range_error as the exception type=C2=A0for failure but =
another may be appropriate.</div><div>bad_enum as an exception=C2=A0type=C2=
=A0contains the value that was bad and the type name that it failed to conv=
ert to.</div><div>This=C2=A0would allow people to extract the values to con=
struct their own error messages (perhaps in other languages like French etc=
..).</div><div><br></div><div>If std::bad_enum is too much API, that could b=
e dropped for just std::range_error or something as long a it contains</div=
><div>a full description of the error I think that&#39;s fine.</div></div><=
/blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>I&#39;d like to know what you and the=C2=A0Committee&#39=
;s disposition towards=C2=A0these ideas and views. Hope this helps.</div></=
div></blockquote><div><br></div><div><br></div><div><div>Thanks for your va=
luable input.</div><div><br></div><div>Regards,</div><div>Maciej</div></div=
><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><div><br></div><div>Thanks</div><div>GM</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/a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd=
%40isocpp.org</a>.<br />

------=_Part_1641_1102541637.1484062268062--

------=_Part_1640_282778673.1484062268061--

.
