220 30492 <dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: enum_cast proposal
Date: Wed, 11 Jan 2017 13:21:14 -0800 (PST)
Lines: 820
Approved: news@gmane.org
Message-ID: <dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org>
References: <efdf2357-00a6-408a-8772-12f99135a880@isocpp.org>
 <57258435-5d82-48e7-8ed7-3c38682418fb@isocpp.org>
 <a35d9f20-9e4f-4789-b7e5-5cb08f99e6bd@isocpp.org>
 <e779f1ca-8f05-7eda-72c8-89a9a5215c62@wanadoo.fr>
 <24e58aad-ecbc-4c83-a21b-de56ea4c1db0@isocpp.org>
 <040e99e3-8f07-409f-3a47-ebdfb2bfb465@wanadoo.fr>
 <1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org>
 <214358e3-699e-f804-4289-14472559a51a@wanadoo.fr>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_3781_1952031667.1484169674856"
X-Trace: blaine.gmane.org 1484169712 15389 195.159.176.226 (11 Jan 2017 21:21:52 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Wed, 11 Jan 2017 21:21:52 +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+bncBCEKFTV6ZUMBBS6D3LBQKGQETKDZJRY@isocpp.org Wed Jan 11 22:21:41 2017
Return-path: <std-proposals+bncBCEKFTV6ZUMBBS6D3LBQKGQETKDZJRY@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f69.google.com ([209.85.213.69])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBS6D3LBQKGQETKDZJRY@isocpp.org>)
	id 1cRQKW-0000Yc-Ho
	for gclcip-std-proposals@m.gmane.org; Wed, 11 Jan 2017 22:21:12 +0100
Original-Received: by mail-vk0-f69.google.com with SMTP id 137sf164935vkl.4
        for <gclcip-std-proposals@m.gmane.org>; Wed, 11 Jan 2017 13:21:16 -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=cqxvn7Sp9usduFLdnHDWJ5WzonKusQHw7fN9EIF0sOw=;
        b=Vad/iiHzB1ySoTS3uOUZZ79/uffqnFq0MI2gPzFHNIDxiruNViHRoekHoJa/EjVKrp
         RCaCa60u1BoWZO7sUE1+aPoVNb+QjiEfVPovX7aHMFDkZjkk1XxU+Fbm7IHI2XqBgEMu
         yjOuy3RZhV4Hx0cJ8sCFaEKdo3sZ/eBHuJUDykd+6WjKlCEx4C4KLnBgK/mi6vSWZcBH
         P7S4p0sZfrpZfCJUVqoKGsw/YWsUX/mRdFz0PVgKEJzMH8A9cLQF68CPGI1XibRyh577
         WL2YyGL6vt/qnO1l8tKCbYOSdK8rbyarMr3PDo5UEya2hc6uHajXjbAKxtBs4vMKSo6Q
         DVxg==
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=cqxvn7Sp9usduFLdnHDWJ5WzonKusQHw7fN9EIF0sOw=;
        b=ld5L513aPZOHKIcxu0vbBbW0baSiHxToa0RdxVqBJSf2dMyHX4GKgQk02zfSDPwToA
         951JkfWvzUJTzdysEAeZP4mDG6+gLcQ89I0s6+1T/NOcdnqTR6I97Mvs8hXDvecCGfqd
         dihtIqaz8NwtGEdnsRjeVvValfkzc+zc95vvCJIPHdqWHs6FYRkZSAo1Sk8JUHYqhTL/
         0K7T1Tbo3aXGQSXbU7wGdPaLX0VI2OBUbGI3qL1YvCCBTaHf9MsMsy/+Rd6BhMvof5f9
         +TqSlgnKs+CtuKS+0kmyMJDBLqvHQmwdIa9prymEEKNHn+AwouerTYL8FhFWHP7ErhVW
         bJQQ==
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=cqxvn7Sp9usduFLdnHDWJ5WzonKusQHw7fN9EIF0sOw=;
        b=G+vCv9DSvtws9xZ+Up+kq0xMzWR3aGPlxHLRJJjEUFBtFj5zjGoKYYZvV55e6dUOEG
         jyByiIE3/Xv10qDftciWfSyzegIO1+INgDnQt4z3EMd/nkkeUOZWmaDWDfY7RuWEwcMe
         lpC+UZudusi58zyd3483GwsOqxl8Cl09kiLGXPdm35Zq24XNNZzOyHXXe147N2bKsx56
         LkQJTRfcOpa4/1wK10CTpE3D5CoITLg6wHOFhvtqpZXLQj1t2Qe9CQvdTiAmeg0iqNLq
         lrbCYemiZ7lZSbDK1kxkyPappNFRZ8fEHcL/ikF+7/iGzBUBMiR/t3ywgvmTruHdrEMT
         etGw==
X-Gm-Message-State: AIkVDXIHZXbGoVrNYL5XSOVEz0w2U5fhg+9OIGVmoRsy2QwF7q+uC55qF/OJ9Rjd+XCnhA==
X-Received: by 10.31.174.140 with SMTP id x134mr2828141vke.6.1484169676331;
        Wed, 11 Jan 2017 13:21:16 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.36.109 with SMTP id p100ls1164692ota.10.gmail; Wed, 11 Jan
 2017 13:21:15 -0800 (PST)
X-Received: by 10.157.61.131 with SMTP id l3mr1137346otc.18.1484169675560;
        Wed, 11 Jan 2017 13:21:15 -0800 (PST)
In-Reply-To: <214358e3-699e-f804-4289-14472559a51a@wanadoo.fr>
X-Original-Sender: jmckesson@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:30492
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/30492>

------=_Part_3781_1952031667.1484169674856
Content-Type: multipart/alternative; 
	boundary="----=_Part_3782_848304554.1484169674858"

------=_Part_3782_848304554.1484169674858
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Wednesday, January 11, 2017 at 1:52:11 PM UTC-5, Vicente J. Botet=20
Escriba wrote:
>
> Le 11/01/2017 =C3=A0 00:06, Nicol Bolas a =C3=A9crit :
>
> On Tuesday, January 10, 2017 at 5:26:11 PM UTC-5, Vicente J. Botet Escrib=
a=20
> wrote:=20
>>
>> Le 10/01/2017 =C3=A0 20:30, Nicol Bolas a =C3=A9crit :
>>
>> On Tuesday, January 10, 2017 at 1:49:05 PM UTC-5, Vicente J. Botet=20
>> Escriba wrote:=20
>>>
>>> Le 10/01/2017 =C3=A0 16:31, m.ce...@gmail.com a =C3=A9crit :
>>>
>>>
>>> W dniu wtorek, 10 stycznia 2017 13:49:00 UTC+1 u=C5=BCytkownik=20
>>> gmis...@gmail.com napisa=C5=82:=20
>>>>
>>>>
>>>>
>>>> On Tuesday, January 3, 2017 at 10:56:05 PM UTC+13, m.ce...@gmail.com=
=20
>>>> wrote:=20
>>>>>
>>>>> Hi,=20
>>>>>
>>>>>
>>> I'll try to create a first draft after I get some more comments w.r.t t=
o=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=20
>>> to_chars/from_chars.
>>> =20
>>>
>>>>
>>>> I hope this post assists you with your proposal. My suggestions are fo=
r=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.
>>>
>>>
>>> I believe we need two checking functions:
>>> * is_enumerator : checks if the explicit conversion from the integer is=
=20
>>> one of the explicit enumerators
>>> * is_in_enum_range: checks if the integer is in the range of valid=20
>>> values. This is the precondition of the static_cast.
>>>
>>> IIUC when the underlying type is explicit, the range of values are the=
=20
>>> range of the underlying type. However when the underlying type is impli=
cit=20
>>> the range goes from the min to the max of the values of the enumerators=
..
>>>
>>
>> Right, but `is_enumerator` is a functional superset of=20
>> `is_in_enum_range`. Do people really need to ask *only* if a value is in=
=20
>> the range of an enumerator?
>>
>> I don't follow you. You surely wanted to say subset
>>
>
> Yes, I did. My mistake.
> =20
>
>>
>> The standard says in 7.2/8 :=20
>>
>>
>>    1.=20
>>   =20
>>    8  For an enumeration whose underlying type is fixed, the values of=
=20
>>    the enumeration are the values of the underlying type. Otherwise, for=
 an=20
>>    enumeration where emin is the smallest enumerator and emax is the=20
>>    largest, the values of the enumeration are the values in the range bm=
in=20
>>    to bmax, defined as follows: Let K be 1 for a two=E2=80=99s complemen=
t=20
>>    representation and 0 for a ones=E2=80=99 complement or sign-magnitude=
=20
>>    representation. bmax is the smallest value greater than or equal to=
=20
>>    max(|emin| =E2=88=92 K, |emax|) and equal to 2M =E2=88=92 1, where M =
is a=20
>>    non-negative integer. bmin is zero if emin is non-negative and =E2=88=
=92(bmax +=20
>>    K) otherwise. The size of the smallest bit-field large enough to hold=
=20
>>    all the values of the enumeration type is max(M,1) if bmin is zero=20
>>    and M + 1 otherwise. *It is possible to define an enumeration that=20
>>    has values not defined by any of its enumerators.* If the enumerator-=
list=20
>>    is empty, the values of the enumeration are as if the enumeration had=
=20
>>    a single enumerator with value 0.=20
>>   =20
>>
>> For me enumerators are any one of the named enum values. This set is a=
=20
>> subset  not a superset of the range of valid values.
>>
>> As I said, until we don't have enums that consists only of the=20
>> enumerators, there would be always the need to check if a value is a val=
id=20
>> value for the enumeration.
>>
> =20
>>
> We could define a class that accepts only the enumerators as valid values=
,=20
>> but the language enums can accept more values.
>> This is way I believe that the two checks are needed.
>>
>
> Here's the thing.
>
> There are enumerations that have a fixed underlying type (`enum class`es=
=20
> use `int` by default), and there are enumerations that have an implied=20
> underlying type (ie: non-`class` enums without a specified type).
>
> What is important is the range of values.
>
>
> The question I have to ask is this: if you have an integer, why do you=20
> need to know if it will fit within the range of an enum with an implied=
=20
> underlying type?
>
> Because initializing the enum with an integer out of range is UB.
>

You're misunderstanding my question.

The situation you describe is one where:

1. You have an integer of arbitrary origin.

2. You want to convert it to an enum type.

3. That integer *does not match* one of the enumerators in that type.

4. The enum type does not have a fixed underlying type.

What goal are you trying to achieve with all this? Or more to the point,=20
why are you incapable of simply giving the enum an underlying type and thus=
=20
making the question moot?

> What problem are you trying to solve? What code are you trying to write?
>
> If the enum has a fixed underlying type, then you might need to know the=
=20
> range because you're using the enum as an ad-hoc strongly typed integer.
>
> Right.
>
> I personally despise this obvious abuse of a language feature, but C++17=
=20
> has effectively canonized it, so there it is. Alternatively, you may be=
=20
> using that enum as a bitfield.
>
> The thing is, that is a solved problem: get the underlying type with=20
> `std::underlying_type_t<E>`. That, and its corresponding `numeric_limits`=
=20
> will tell you everything you need to know about the range of that=20
> enumeration.
>
> I don't want to solve problems that are already solved. We don't need any=
=20
> modification on the compiler to solve this case, but if it solve the more=
=20
> dificult case it could  solve this as well.
>
>
> But if the enum has an implied underlying type, then why would you need t=
o=20
> know if a particular integer (which does not match any enumerator) is=20
> within the valid range for that enum?
>
> Because this is legal. I can assign it a value on the specified range.=20
> That's all. If I want my code to be outside the UB world I should be able=
=20
> to check on the conditions. I can of course do it for each particular cas=
e,=20
> but what we are talking of here is about what the compiler could do for u=
s=20
> in a generic way.
>
> What are you trying to do that you need to do this?
>
> This is not a use case I would write myself, but I've see it a lot of=20
> times. When you use enums as flags of an bitset
> enum class X { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x04, ALL 0x08};
>
> The valid enumerators  don't correspond to the valid range, that in this=
=20
> case is any value between 0 and 8.
>

But we can already answer that question. `X` is an `enum class`. As such,=
=20
it *always* has a fixed underlying type. If you don't specify one, then it=
=20
shall be `int`, and therefore `X` can legally assume any `int` value.

So the `std::underlying_type`-based solution will work fine.

It should also be noted that the standard-specified range guarantees the=20
ability to use an enum with an implied underlying type as a bitfield. That=
=20
is, if you perform bitwise operations with the enumerators, the results are=
=20
guaranteed to fit in the range. So you have nothing to worry about for that=
=20
use case.

> If you don't have a problem to be solved with such a function, then=20
> there's really no point in adding one.
>
> I was sure you will ask and say this ;-)
>
>
> I don't know why the new C++11 enum with an explicit underlying type have=
=20
>> a different range of valid values.
>> I'll be interested in knowing the rationale.
>>
>
> Because enums are integers. That's the rationale.
>
> I believe that you didn't understood my question. Let me see with an=20
> example.=20
> What is the difference between
>
>     enum class X { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x04, ALL 0x08};
>
> and=20
>
>     enum class Y : unsigned char { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x04=
, ALL=20
> 0x08};
> ?
>
> X has a valid range 0..N, while Y has a valid range 0..255.
>
> Why do we need this difference? Why forcing the underlying type changes=
=20
> the range of valid values?
>

In that case, both have a forced underlying type, as I pointed out above.=
=20
So the reason for the differing ranges of values is obvious.

Now, let's assume you have revised your example to not use `enum class`.=20
`enum X` does not have a fixed underlying type, so its range is determined=
=20
by its enumerators. The reason that is different is because that's how it=
=20
always was before, and there's terribly little reason to change it.

--=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/dbe0b3d3-e7ea-426a-a78d-6681202a4ea7%40isocpp.or=
g.

------=_Part_3782_848304554.1484169674858
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wednesday, January 11, 2017 at 1:52:11 PM UTC-5, Vicent=
e J. Botet Escriba wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
 =20
   =20
 =20
  <div bgcolor=3D"#FFFFFF" text=3D"#000000">
    <div>Le 11/01/2017 =C3=A0 00:06, Nicol Bolas a
      =C3=A9crit=C2=A0:<br>
    </div>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">On Tuesday, January 10, 2017 at 5:26:11 PM UTC-5,
        Vicente J. Botet Escriba wrote:
        <blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
          <div bgcolor=3D"#FFFFFF" text=3D"#000000">
            <div>Le 10/01/2017 =C3=A0 20:30, Nicol Bolas a =C3=A9crit=C2=A0=
:<br>
            </div>
            <blockquote type=3D"cite">
              <div dir=3D"ltr">On Tuesday, January 10, 2017 at 1:49:05 PM
                UTC-5, Vicente J. Botet Escriba wrote:
                <blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
                  <div bgcolor=3D"#FFFFFF" text=3D"#000000">
                    <div>Le 10/01/2017 =C3=A0 16:31, <a rel=3D"nofollow">m.=
ce...@gmail.com</a>
                      a =C3=A9crit=C2=A0:<br>
                    </div>
                    <blockquote type=3D"cite">
                      <div dir=3D"ltr"><br>
                        W dniu wtorek, 10 stycznia 2017 13:49:00 UTC+1
                        u=C5=BCytkownik <a>gmis...@gmail.com</a>
                        napisa=C5=82:
                        <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"><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"marg=
in:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);bo=
rder-left-width:1px;border-left-style:solid">
                              <div dir=3D"ltr">Hi,
                                <div><br>
                                </div>
                              </div>
                            </blockquote>
                          </div>
                        </blockquote>
                        <br>
                        <div>I&#39;ll try to create a first draft after I
                          get some more comments w.r.t to exceptions.</div>
                        <div>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-left: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>
                            <div>=C2=A0// compiler=C2=A0magic:</div>
                            <div>=C2=A0// Calling this routine causes the
                              compiler to generate or a call a routine</div=
>
                            <div>=C2=A0// that returns 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.<br>
                        </div>
                        <div>Also is_enum seems redundant to me, since
                          to_enum already reports</div>
                        <div>if convertion succeeded instead of:</div>
                        <div>
                          <div style=3D"border:1px solid rgb(187,187,187);w=
ord-wrap:break-word;background-color:rgb(250,250,250)"><code>
                              <div><span style=3D"color:#008">if</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">is_enum</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#606">MyEnum</span><span style=3D"color:#660">&gt;(</span><=
span style=3D"color:#066">139</span><span style=3D"color:#660">))</span></d=
iv>
                            </code></div>
                          <br>
                        </div>
                        <div>you could write:</div>
                        <div>
                          <div style=3D"border:1px solid rgb(187,187,187);w=
ord-wrap:break-word;background-color:rgb(250,250,250)"><code>
                              <div><span style=3D"color:#008">if</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">to_enum</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#606">MyEnum</span><span style=3D"color:#660">&gt;(</span><=
span style=3D"color:#066">139</span><span style=3D"color:#660">).</span><sp=
an style=3D"color:#000">is_valid</span><span style=3D"color:#660"><wbr>)</s=
pan></div>
                            </code></div>
                          <br>
                        </div>
                        <div>or even:</div>
                        <div>
                          <div style=3D"border:1px solid rgb(187,187,187);w=
ord-wrap:break-word;background-color:rgb(250,250,250)"><code>
                              <div><span style=3D"color:#008">if</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">to_enum</span><span style=3D"color:#660">&lt;</span><span=
 style=3D"color:#606">MyEnum</span><span style=3D"color:#660">&gt;(</span><=
span style=3D"color:#066">139</span><span style=3D"color:#660">))</span></d=
iv>
                            </code></div>
                          if we add explicit bool convertion operator
                          for to_enum_result.</div>
                        <div><br>
                        </div>
                        <div><br>
                        </div>
                      </div>
                    </blockquote>
                    I believe we need two checking functions:<br>
                    * is_enumerator : checks if the explicit conversion
                    from the integer is one of the explicit enumerators<br>
                    * is_in_enum_range: checks if the integer is in the
                    range of valid values. This is the precondition of
                    the static_cast.<br>
                    <br>
                    IIUC when the underlying type is explicit, the range
                    of values are the range of the underlying type.
                    However when the underlying type is implicit the
                    range goes from the min to the max of the values of
                    the enumerators.<br>
                  </div>
                </blockquote>
                <div><br>
                  Right, but `is_enumerator` is a functional superset of
                  `is_in_enum_range`. Do people really need to ask <i>only<=
/i>
                  if a value is in the range of an enumerator?<br>
                </div>
              </div>
            </blockquote>
            I don&#39;t follow you. You surely wanted to say subset<br>
          </div>
        </blockquote>
        <div><br>
          Yes, I did. My mistake.<br>
          =C2=A0</div>
        <blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
          <div bgcolor=3D"#FFFFFF" text=3D"#000000"> <br>
            The standard says in 7.2/8 :
            <blockquote>
              <div title=3D"Page 190">
                <div>
                  <div>
                    <ol start=3D"6" style=3D"list-style-type:none">
                      <li>
                        <p><span style=3D"font-size:7.000000pt;font-family:=
&#39;LMRoman7&#39;;vertical-align:2.000000pt">8
                            =C2=A0</span><span style=3D"font-size:10.000000=
pt;font-family:&#39;LMRoman10&#39;">For
                            an enumeration whose underlying type is
                            fixed, the values of the enumeration are the
                            values of the underlying type. Otherwise,
                            for an enumeration where </span><span style=3D"=
font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">e</span><span s=
tyle=3D"font-size:7.000000pt;font-family:&#39;LMRoman7&#39;;font-style:ital=
ic;vertical-align:-1.000000pt">min
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            the smallest enumerator and </span><span style=
=3D"font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">e</span><sp=
an style=3D"font-size:7.000000pt;font-family:&#39;LMRoman7&#39;;font-style:=
italic;vertical-align:-1.000000pt">max
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            the largest, the values of the enumeration
                            are the values in the range </span><span style=
=3D"font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">b</span><sp=
an style=3D"font-size:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertic=
al-align:-1.000000pt">min
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">to
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMMathItalic10&#39;">b</span><span style=3D"font-size:7.000000p=
t;font-family:&#39;LMMathItalic7&#39;;vertical-align:-1.000000pt">max</span=
><span style=3D"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;">, de=
fined as
                            follows: Let </span><span style=3D"font-size:10=
..000000pt;font-family:&#39;LMMathItalic10&#39;">K
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">be
                            1 for a two=E2=80=99s complement representation=
 and
                            0 for a ones=E2=80=99 complement or sign-magnit=
ude
                            representation. </span><span style=3D"font-size=
:10.000000pt;font-family:&#39;LMMathItalic10&#39;">b</span><span style=3D"f=
ont-size:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertical-align:-1.0=
00000pt">max
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            the smallest value greater than or equal to
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMMathItalic10&#39;">max</span><span style=3D"font-size:10.0000=
00pt;font-family:&#39;LMRoman10&#39;">(</span><span style=3D"font-size:10.0=
00000pt;font-family:&#39;LMMathSymbols10&#39;">|</span><span style=3D"font-=
size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">e</span><span style=
=3D"font-size:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertical-align=
:-1.000000pt">min</span><span style=3D"font-size:10.000000pt;font-family:&#=
39;LMMathSymbols10&#39;">| =E2=88=92 </span><span style=3D"font-size:10.000=
000pt;font-family:&#39;LMMathItalic10&#39;">K, </span><span style=3D"font-s=
ize:10.000000pt;font-family:&#39;LMMathSymbols10&#39;">|</span><span style=
=3D"font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">e</span><sp=
an style=3D"font-size:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertic=
al-align:-1.000000pt">max</span><span style=3D"font-size:10.000000pt;font-f=
amily:&#39;LMMathSymbols10&#39;">|</span><span style=3D"font-size:10.000000=
pt;font-family:&#39;LMRoman10&#39;">) </span><span style=3D"font-size:10.00=
0000pt;font-family:&#39;LMRoman10&#39;">and
                            equal to </span><span style=3D"font-size:10.000=
000pt;font-family:&#39;LMRoman10&#39;">2</span><span style=3D"font-size:7.0=
00000pt;font-family:&#39;LMMathItalic7&#39;;vertical-align:4.000000pt">M
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMMathSymbols10&#39;">=E2=88=92
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">1</span><span style=3D"font-size:10.000000pt;fo=
nt-family:&#39;LMRoman10&#39;">, where </span><span style=3D"font-size:10.0=
00000pt;font-family:&#39;LMMathItalic10&#39;">M </span><span style=3D"font-=
size:10.000000pt;font-family:&#39;LMRoman10&#39;">is a non-negative
                            integer. </span><span style=3D"font-size:10.000=
000pt;font-family:&#39;LMMathItalic10&#39;">b</span><span style=3D"font-siz=
e:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertical-align:-1.000000pt=
">min
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            zero if </span><span style=3D"font-size:10.0000=
00pt;font-family:&#39;LMMathItalic10&#39;">e</span><span style=3D"font-size=
:7.000000pt;font-family:&#39;LMMathItalic7&#39;;vertical-align:-1.000000pt"=
>min
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            non-negative and </span><span style=3D"font-siz=
e:10.000000pt;font-family:&#39;LMMathSymbols10&#39;">=E2=88=92</span><span =
style=3D"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;">(</span><sp=
an style=3D"font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">b</=
span><span style=3D"font-size:7.000000pt;font-family:&#39;LMMathItalic7&#39=
;;vertical-align:-1.000000pt">max
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">+
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMMathItalic10&#39;">K</span><span style=3D"font-size:10.000000=
pt;font-family:&#39;LMRoman10&#39;">) </span><span style=3D"font-size:10.00=
0000pt;font-family:&#39;LMRoman10&#39;">otherwise.
                            The size of the smallest bit-field large
                            enough to hold all the values of the
                            enumeration type is </span><span style=3D"font-=
size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">max</span><span styl=
e=3D"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;">(</span><span s=
tyle=3D"font-size:10.000000pt;font-family:&#39;LMMathItalic10&#39;">M,</spa=
n><span style=3D"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;">1) =
</span><span style=3D"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;=
">if
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMMathItalic10&#39;">b</span><span style=3D"font-size:7.000000p=
t;font-family:&#39;LMMathItalic7&#39;;vertical-align:-1.000000pt">min
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            zero and </span><span style=3D"font-size:10.000=
000pt;font-family:&#39;LMMathItalic10&#39;">M
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">+
                            1 </span><span style=3D"font-size:10.000000pt;f=
ont-family:&#39;LMRoman10&#39;">otherwise.
                            <b>It is possible to define an enumeration
                              that has values not defined by any of its
                              enumerators.</b> If the </span><span style=3D=
"font-size:10.000000pt;font-family:&#39;LMRoman10&#39;;font-style:italic">e=
numerator-list
                          </span><span style=3D"font-size:10.000000pt;font-=
family:&#39;LMRoman10&#39;">is
                            empty, the values of the enumeration are as
                            if the enumeration had a single enumerator
                            with value 0. </span></p>
                      </li>
                    </ol>
                  </div>
                </div>
              </div>
              <br>
            </blockquote>
            For me enumerators are any one of the named enum values.
            This set is a subset=C2=A0 not a superset of the range of valid
            values.<br>
            <br>
            As I said, until we don&#39;t have enums that consists only of
            the enumerators, there would be always the need to check if
            a value is a valid value for the enumeration.<br>
          </div>
        </blockquote>
        <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left:1px solid rgb(204,204,204);padding-left:1ex">
          <div>=C2=A0</div>
        </blockquote>
        <blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
          <div bgcolor=3D"#FFFFFF" text=3D"#000000"> We could define a clas=
s
            that accepts only the enumerators as valid values, but the
            language enums can accept more values.<br>
            This is way I believe that the two checks are needed.<br>
          </div>
        </blockquote>
        <div><br>
          Here&#39;s the thing.<br>
          <br>
          There are enumerations that have a fixed underlying type
          (`enum class`es use `int` by default), and there are
          enumerations that have an implied underlying type (ie:
          non-`class` enums without a specified type).<br>
        </div>
      </div>
    </blockquote>
    What is important is the range of values.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          The question I have to ask is this: if you have an integer,
          why do you need to know if it will fit within the range of an
          enum with an implied underlying type?</div>
      </div>
    </blockquote>
    Because initializing the enum with an integer out of range is UB.<br></=
div></blockquote><div><br>You&#39;re misunderstanding my question.<br><br>T=
he situation you describe is one where:<br><br>1. You have an integer of ar=
bitrary origin.<br><br>2. You want to convert it to an enum type.<br><br>3.=
 That integer <i>does not match</i> one of the enumerators in that type.<br=
><br>4. The enum type does not have a fixed underlying type.<br><br>What go=
al are you trying to achieve with all this? Or more to the point, why are y=
ou incapable of simply giving the enum an underlying type and thus making t=
he question moot?<br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v bgcolor=3D"#FFFFFF" text=3D"#000000">
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div> What problem are you trying to solve? What code are you
          trying to write?<br>
          <br>
          If the enum has a fixed underlying type, then you might need
          to know the range because you&#39;re using the enum as an ad-hoc
          strongly typed integer.</div>
      </div>
    </blockquote>
    Right.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div> I personally despise this obvious abuse of a language
          feature, but C++17 has effectively canonized it, so there it
          is. Alternatively, you may be using that enum as a bitfield.<br>
          <br>
          The thing is, that is a solved problem: get the underlying
          type with `std::underlying_type_t&lt;E&gt;`. That, and its
          corresponding `numeric_limits` will tell you everything you
          need to know about the range of that enumeration.<br>
        </div>
      </div>
    </blockquote>
    I don&#39;t want to solve problems that are already solved. We don&#39;=
t
    need any modification on the compiler to solve this case, but if it
    solve the more dificult case it could=C2=A0 solve this as well.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          But if the enum has an implied underlying type, then why would
          you need to know if a particular integer (which does not match
          any enumerator) is within the valid range for that enum?</div>
      </div>
    </blockquote>
    Because this is legal. I can assign it a value on the specified
    range. That&#39;s all. If I want my code to be outside the UB world I
    should be able to check on the conditions. I can of course do it for
    each particular case, but what we are talking of here is about what
    the compiler could do for us in a generic way.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div> What are you trying to do that you need to do this?<br>
        </div>
      </div>
    </blockquote>
    This is not a use case I would write myself, but I&#39;ve see it a lot
    of times. When you use enums as flags of an bitset<br>
    enum class X { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x04, ALL 0x08};<br>
    <br>
    The valid enumerators=C2=A0 don&#39;t correspond to the valid range, th=
at in
    this case is any value between 0 and 8.<br></div></blockquote><div><br>=
But we can already answer that question. `X` is an `enum class`. As such, i=
t <i>always</i> has a fixed underlying type. If you don&#39;t specify one, =
then it shall be `int`, and therefore `X` can legally assume any `int` valu=
e.<br><br>So the `std::underlying_type`-based solution will work fine.<br><=
br>It should also be noted that the standard-specified range guarantees the=
 ability to use an enum with an implied underlying type as a bitfield. That=
 is, if you perform bitwise operations with the enumerators, the results ar=
e guaranteed to fit in the range. So you have nothing to worry about for th=
at use case.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgc=
olor=3D"#FFFFFF" text=3D"#000000">
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          If you don&#39;t have a problem to be solved with such a function=
,
          then there&#39;s really no point in adding one.<br>
        </div>
      </div>
    </blockquote>
    I was sure you will ask and say this ;-)<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <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 bgcolor=3D"#FFFFFF" text=3D"#000000"> I don&#39;t know why t=
he
            new C++11 enum with an explicit underlying type have a
            different range of valid values.<br>
            I&#39;ll be interested in knowing the rationale.<br>
          </div>
        </blockquote>
        <div><br>
          Because enums are integers. That&#39;s the rationale.<br>
        </div>
      </div>
    </blockquote>
    I believe that you didn&#39;t understood my question. Let me see with a=
n
    example. <br>
    What is the difference between<br>
    <br>
    =C2=A0=C2=A0=C2=A0 enum class X { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x0=
4, ALL 0x08};<br>
    <br>
    and <br>
    <br>
    =C2=A0=C2=A0=C2=A0 enum class Y : unsigned char { NONE=3D0, A=3D0x01, B=
=3D0x02, C=3D0x04,
    ALL 0x08};<br>
    ?<br>
    <br>
    X has a valid range 0..N, while Y has a valid range 0..255.<br>
    <br>
    Why do we need this difference? Why forcing the underlying type
    changes the range of valid values?<br></div></blockquote><div><br>In th=
at case, both have a forced underlying type, as I pointed out above. So the=
 reason for the differing ranges of values is obvious.<br><br>Now, let&#39;=
s assume you have revised your example to not use `enum class`. `enum X` do=
es not have a fixed underlying type, so its range is determined by its enum=
erators. The reason that is different is because that&#39;s how it always w=
as before, and there&#39;s terribly little reason to change it.<br></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/dbe0b3d3-e7ea-426a-a78d-6681202a4ea7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dbe0b3d3-e7ea-426a-a78d-6681202a4ea7=
%40isocpp.org</a>.<br />

------=_Part_3782_848304554.1484169674858--

------=_Part_3781_1952031667.1484169674856--

.
