220 30486 <214358e3-699e-f804-4289-14472559a51a@wanadoo.fr> article
Path: news.gmane.org!.POSTED!not-for-mail
From: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: enum_cast proposal
Date: Wed, 11 Jan 2017 19:52:08 +0100
Lines: 778
Approved: news@gmane.org
Message-ID: <214358e3-699e-f804-4289-14472559a51a@wanadoo.fr>
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>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="------------B0E4ED9DE0FEA910FFB5435C"
X-Trace: blaine.gmane.org 1484160732 30378 195.159.176.226 (11 Jan 2017 18:52:12 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Wed, 11 Jan 2017 18:52:12 +0000 (UTC)
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0)
 Gecko/20100101 Thunderbird/45.6.0
Cc: m.cencora@gmail.com, gmisocpp@gmail.com
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBDH67CONY4PBBWX53HBQKGQERR747WA@isocpp.org Wed Jan 11 19:52:06 2017
Return-path: <std-proposals+bncBDH67CONY4PBBWX53HBQKGQERR747WA@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-lf0-f71.google.com ([209.85.215.71])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDH67CONY4PBBWX53HBQKGQERR747WA@isocpp.org>)
	id 1cRO0E-0007CM-6S
	for gclcip-std-proposals@m.gmane.org; Wed, 11 Jan 2017 19:52:06 +0100
Original-Received: by mail-lf0-f71.google.com with SMTP id l127sf83412334lfl.3
        for <gclcip-std-proposals@m.gmane.org>; Wed, 11 Jan 2017 10:52:11 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=subject:to:references:cc:from:message-id:date:user-agent
         :mime-version:in-reply-to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=AH57GaIfHMtWulFcbo7H/J6GIil67I9+2eDcT01RQ8g=;
        b=fmAfCFY86+F72BDmMJfr+vWw1izL41A3K+KVQ7ImJIML0HyQWyYbiDmsu0v1xCIvFv
         sucwoUgW29ZDBsuEbQN2RpmcwO2Q4CKnfKpgMO17aAsvzcn5nDGiuxbvp4Xq3WPVzfzU
         yqfBBAKat5JWZ+yDyvxbkfcpCc0KCisfl/jDABv2nAWzYlXh4lCXg3HLFBlOCffr8l17
         5Eu+ze2wEMJ3w87PA29N2mggBtKIGreKr7D55QeKKquO1L39grIU6TJP5YLbVB6Cy0Qd
         PeiPr3dANOYmVcaxRURKLwPxxE9BKvBwB2d6a/SOcK/og0FK0q4QFUy6bHtBUb9qKhee
         Yzjw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:subject:to:references:cc:from:message-id:date
         :user-agent:mime-version:in-reply-to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=AH57GaIfHMtWulFcbo7H/J6GIil67I9+2eDcT01RQ8g=;
        b=eyuywBEltgWKSQJyEPRRun/gtSqRjWioQchhcfnoN9jsDJSNZfvmdDo0Cq4ro2jfTo
         f7zoj1mExniP8wQxzjf8SlnMkNQhp3ETBPw8p8TsUr3/fXZAHeeqhrmNIH9fT3/Brums
         rbSpwqTNu8NZ70xO26crU6SVRANEuazTH5NYeVyTyKy2pdEyjuLNWt0EqFGluWQxo2sk
         QE97qZWg7N//RCiJQB16fogN74FsE+JEPDE+/jxSjSAWHKKR9hUAmuV8BD5dVplEUfGo
         W+nyhnn2yNeGR5PbqrYhXh6HlT9g2a0DqS9WvRncCPUH3xjO+3z9PcNWYIyBPT5Ai0N6
         WMSA==
X-Gm-Message-State: AIkVDXJW1L86NJX93fkgTxH27FvKwdkrCLH4zE3T90rOCzwcVZMV8wz0W/n+KJX9putTgw==
X-Received: by 10.25.195.195 with SMTP id t186mr927774lff.9.1484160731057;
        Wed, 11 Jan 2017 10:52:11 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.28.14.74 with SMTP id 71ls864152wmo.16.gmail; Wed, 11 Jan 2017
 10:52:09 -0800 (PST)
X-Received: by 10.194.86.34 with SMTP id m2mr6272852wjz.173.1484160729696;
        Wed, 11 Jan 2017 10:52:09 -0800 (PST)
Original-Received: from smtp.smtpout.orange.fr (smtp13.smtpout.orange.fr. [80.12.242.135])
        by mx.google.com with ESMTPS id k83si5529333wmk.31.2017.01.11.10.52.09
        for <std-proposals@isocpp.org>
        (version=TLS1 cipher=AES128-SHA bits=128/128);
        Wed, 11 Jan 2017 10:52:09 -0800 (PST)
Received-SPF: neutral (google.com: 80.12.242.135 is neither permitted nor denied by best guess record for domain of vicente.botet@wanadoo.fr) client-ip=80.12.242.135;
Original-Received: from imac-de-vicente-botet-escriba.home ([2.11.61.75])
	by mwinf5d76 with ME
	id X6s81u00E1dPwbE036s852; Wed, 11 Jan 2017 19:52:09 +0100
X-ME-Helo: imac-de-vicente-botet-escriba.home
X-ME-Auth: dmljZW50ZS5ib3RldEB3YW5hZG9vLmZy
X-ME-Date: Wed, 11 Jan 2017 19:52:09 +0100
X-ME-IP: 2.11.61.75
In-Reply-To: <1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org>
X-Original-Sender: vicente.botet@wanadoo.fr
X-Original-Authentication-Results: mx.google.com;       spf=neutral
 (google.com: 80.12.242.135 is neither permitted nor denied by best guess
 record for domain of vicente.botet@wanadoo.fr) smtp.mailfrom=vicente.botet@wanadoo.fr
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:30486
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/30486>

This is a multi-part message in MIME format.
--------------B0E4ED9DE0FEA910FFB5435C
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

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=20
> Escriba wrote:
>
>     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 Escriba wrote:
>>
>>         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
>>>         gmis...@gmail.com napisa=C5=82:
>>>
>>>
>>>
>>>             On Tuesday, January 3, 2017 at 10:56:05 PM UTC+13,
>>>             m.ce...@gmail.com wrote:
>>>
>>>                 Hi,
>>>
>>>
>>>         I'll try to create a first draft after I get some more
>>>         comments w.r.t to 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.
>>>
>>>
>>>             I hope this post assists you with your proposal. My
>>>             suggestions are for 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 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 one of the explicit enumerators
>>         * is_in_enum_range: checks if the integer is in the range of
>>         valid values. This is the precondition of the static_cast.
>>
>>         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.
>>
>>
>>     Right, but `is_enumerator` is a functional superset of
>>     `is_in_enum_range`. Do people really need to ask /only/ if a
>>     value is in the range of an enumerator?
>     I don't follow you. You surely wanted to say subset
>
>
> Yes, I did. My mistake.
>
>
>     The standard says in 7.2/8 :
>
>         6.
>
>             8 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 emin is the
>             smallest enumerator and emax is the largest, the values of
>             the enumeration are the values in the range bmin to bmax,
>             defined as follows: Let K be 1 for a two=E2=80=99s complement
>             representation and 0 for a ones=E2=80=99 complement or
>             sign-magnitude representation. bmax is the smallest value
>             greater than or equal to max(|emin| =E2=88=92 K, |emax|) and =
equal
>             to 2M =E2=88=92 1, where M is a non-negative integer. bmin is=
 zero
>             if emin is non-negative and =E2=88=92(bmax + K) otherwise. Th=
e
>             size of the smallest bit-field large enough to hold all
>             the values of the enumeration type is max(M,1) if bmin is
>             zero and M + 1 otherwise. *It is possible to define an
>             enumeration that has values not defined by any of its
>             enumerators.* If the enumerator-list is empty, the values
>             of the enumeration are as if the enumeration had a single
>             enumerator with value 0.
>
>
>     For me enumerators are any one of the named enum values. This set
>     is a subset  not a superset of the range of valid values.
>
>     As I said, until we don'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.
>
>     We could define a class that accepts only the enumerators as valid
>     values, 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=20
> class`es use `int` by default), and there are enumerations that have=20
> an implied underlying type (ie: non-`class` enums without a specified=20
> 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=20
> implied underlying type?
Because initializing the enum with an integer out of range is UB.
> 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=20
> the range because you're using the enum as an ad-hoc strongly typed=20
> integer.
Right.
> I personally despise this obvious abuse of a language feature, but=20
> C++17 has effectively canonized it, so there it is. Alternatively, you=20
> may be 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=20
> `numeric_limits` will tell you everything you need to know about the=20
> range of that enumeration.
I don't want to solve problems that are already solved. We don't need=20
any modification on the compiler to solve this case, but if it solve the=20
more dificult case it could  solve this as well.
>
> But if the enum has an implied underlying type, then why would you=20
> need to know if a particular integer (which does not match any=20
> enumerator) is 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=20
able to check on the conditions. I can of course do it for each=20
particular case, but what we are talking of here is about what the=20
compiler could do for us 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.
>
> 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 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.
What is the difference between

     enum class X { NONE=3D0, A=3D0x01, B=3D0x02, C=3D0x04, ALL 0x08};

and

     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?

Vicente

--=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/214358e3-699e-f804-4289-14472559a51a%40wanadoo.f=
r.

--------------B0E4ED9DE0FEA910FFB5435C
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    <div class=3D"moz-cite-prefix">Le 11/01/2017 =C3=A0 00:06, Nicol Bolas =
a
      =C3=A9crit=C2=A0:<br>
    </div>
    <blockquote
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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.8ex;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
                        moz-do-not-send=3D"true" rel=3D"nofollow">m.ce...@g=
mail.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 moz-do-not-send=3D"true">gmis...=
@gmail.com</a>
                        napisa=C5=82:
                        <blockquote class=3D"gmail_quote"
                          style=3D"margin:0;margin-left:0.8ex;border-left:1=
px
                          #ccc solid;padding-left:1ex">
                          <div dir=3D"ltr"><br>
                            <br>
                            On Tuesday, January 3, 2017 at 10:56:05 PM
                            UTC+13, <a moz-do-not-send=3D"true">m.ce...@gma=
il.com</a>
                            wrote:
                            <blockquote class=3D"gmail_quote"
                              style=3D"margin:0px 0px 0px
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width=
:1px;border-left-style:solid">
                              <div dir=3D"ltr">Hi,
                                <div><br>
                                </div>
                              </div>
                            </blockquote>
                          </div>
                        </blockquote>
                        <br>
                        <div>I'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'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:1=
px
                          #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's</div>
                            <div>=C2=A0// values. otherwise false.</div>
                            <div>}</div>
                          </div>
                        </blockquote>
                        <div><br>
                        </div>
                        <div>'is_enum' 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);word-wrap:break-word;backgroun=
d-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
                                  style=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></div>
                            </code></div>
                          <br>
                        </div>
                        <div>you could write:</div>
                        <div>
                          <div style=3D"border:1px solid
                            rgb(187,187,187);word-wrap:break-word;backgroun=
d-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
                                  style=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><span
                                  style=3D"color:#000">is_valid</span><span
                                  style=3D"color:#660"><wbr>)</span></div>
                            </code></div>
                          <br>
                        </div>
                        <div>or even:</div>
                        <div>
                          <div style=3D"border:1px solid
                            rgb(187,187,187);word-wrap:break-word;backgroun=
d-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
                                  style=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></div>
                            </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'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.8ex;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:'LMRoman7';vertical-align:2.00000=
0pt">8
                            =C2=A0</span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">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:'LMM=
athItalic10'">e</span><span
style=3D"font-size:7.000000pt;font-family:'LMRoman7';font-style:italic;vert=
ical-align:-1.000000pt">min
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            the smallest enumerator and </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">e</span><span
style=3D"font-size:7.000000pt;font-family:'LMRoman7';font-style:italic;vert=
ical-align:-1.000000pt">max
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            the largest, the values of the enumeration
                            are the values in the range </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">min
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">to
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">max</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">, defined as
                            follows: Let </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">K
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">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:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">max
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            the smallest value greater than or equal to
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">max</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athSymbols10'">|</span><span
style=3D"font-size:10.000000pt;font-family:'LMMathItalic10'">e</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">min</span><span
style=3D"font-size:10.000000pt;font-family:'LMMathSymbols10'">| =E2=88=92 <=
/span><span
style=3D"font-size:10.000000pt;font-family:'LMMathItalic10'">K, </span><spa=
n
style=3D"font-size:10.000000pt;font-family:'LMMathSymbols10'">|</span><span
style=3D"font-size:10.000000pt;font-family:'LMMathItalic10'">e</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">max</span><span
style=3D"font-size:10.000000pt;font-family:'LMMathSymbols10'">|</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">) </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">and
                            equal to </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">2</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:4.=
000000pt">M
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athSymbols10'">=E2=88=92
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">1</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">, where </span><spa=
n
style=3D"font-size:10.000000pt;font-family:'LMMathItalic10'">M </span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">is a non-negative
                            integer. </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">min
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            zero if </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">e</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">min
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            non-negative and </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athSymbols10'">=E2=88=92</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">max
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">+
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">K</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">) </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">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:'LMM=
athItalic10'">max</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">M,</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">1) </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">if
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">b</span><span
style=3D"font-size:7.000000pt;font-family:'LMMathItalic7';vertical-align:-1=
..000000pt">min
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">is
                            zero and </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMM=
athItalic10'">M
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">+
                            1 </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">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:'LMR=
oman10';font-style:italic">enumerator-list
                          </span><span
                            style=3D"font-size:10.000000pt;font-family:'LMR=
oman10'">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'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.8ex;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'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
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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>
    <blockquote
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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're using the enum as an ad-hoc
          strongly typed integer.</div>
      </div>
    </blockquote>
    Right.<br>
    <blockquote
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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't want to solve problems that are already solved. We don'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
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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'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
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      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'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't correspond to the valid range, that i=
n
    this case is any value between 0 and 8.<br>
    <blockquote
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          If you don't have a problem to be solved with such a function,
          then there's really no point in adding one.<br>
        </div>
      </div>
    </blockquote>
    I was sure you will ask and say this ;-)<br>
    <blockquote
      cite=3D"mid:1841091b-9f97-4724-9f95-3193c0fb94fb@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
        </div>
        <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"> I don't know why the
            new C++11 enum with an explicit underlying type have a
            different range of valid values.<br>
            I'll be interested in knowing the rationale.<br>
          </div>
        </blockquote>
        <div><br>
          Because enums are integers. That's the rationale.<br>
        </div>
      </div>
    </blockquote>
    I believe that you didn't understood my question. Let me see with an
    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>
    <br>
    Vicente<br>
  </body>
</html>

<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/214358e3-699e-f804-4289-14472559a51a%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/214358e3-699e-f804-4289-14472559a51a=
%40wanadoo.fr</a>.<br />

--------------B0E4ED9DE0FEA910FFB5435C--

.
