220 30509 <0a4162ad-62ed-1c26-e210-81000402b193@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: Thu, 12 Jan 2017 08:27:56 +0100
Lines: 757
Approved: news@gmane.org
Message-ID: <0a4162ad-62ed-1c26-e210-81000402b193@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>
 <214358e3-699e-f804-4289-14472559a51a@wanadoo.fr>
 <dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="------------5F826F0C354AB6EF0BC1AF2B"
X-Trace: blaine.gmane.org 1484206097 1340 195.159.176.226 (12 Jan 2017 07:28:17 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Thu, 12 Jan 2017 07:28:17 +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+bncBDH67CONY4PBB7673TBQKGQEX4SRDIA@isocpp.org Thu Jan 12 08:28:10 2017
Return-path: <std-proposals+bncBDH67CONY4PBB7673TBQKGQEX4SRDIA@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-wm0-f72.google.com ([74.125.82.72])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDH67CONY4PBB7673TBQKGQEX4SRDIA@isocpp.org>)
	id 1cRZnf-0006mS-DV
	for gclcip-std-proposals@m.gmane.org; Thu, 12 Jan 2017 08:27:55 +0100
Original-Received: by mail-wm0-f72.google.com with SMTP id c206sf1719433wme.3
        for <gclcip-std-proposals@m.gmane.org>; Wed, 11 Jan 2017 23:28:00 -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=xkUTTcFjOz2iiEJY6iT9hozIM7tqwpO0a96shU5Jh0s=;
        b=GRqLxUVbJ6rDE3qw4zvlOgyVF6/ECgDylk2UTtbrskxQfyvXg1fz7CRhZ9+qbzRUdT
         1t1ciJCBHzX30nTlliiR0Y+84oNCgAlSuhsEgIUo34J/RqjmGNAD1rFKeK6NR6dQjnda
         EecmIgOGHj+vs8jlUGjoZhyABwxwq26D3d5n4ZFbCi4LqNJB0jg3f7KUMRl0As7pPFEy
         a9FmELE7lRRW+2xeRuG3HU7mkgzoil4Hq93bVCgjDn4xqDraLIVNtPWOI2/ZUOyCsQDH
         a3GYkbuI8twPCMrL+jMlUqL+p4VcmrGhO6bGYCEm5hMm14GB7shLMCy6nH14oO7G2c4I
         MWsQ==
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=xkUTTcFjOz2iiEJY6iT9hozIM7tqwpO0a96shU5Jh0s=;
        b=iuItQezJVg9ux07OUkBQwvazW3FUXYLDoqDNM2xGo49jyvseM/V0r1qR5GRchAR7tj
         BVF60URx33DrfXd77OQqqzbzHS/qRIyXShEo+T8H+NDWTnZOzMC+mo/XmaTDQA3JUbug
         ybMAGgPZveea+5zz+paC5wFUup+jSbG7IXEgfnQBJ3GlAUb0PSGC6iJS7ExGV2dwl+bF
         NHAPLjwvVR8XQYsQCiqlRel/QZ6GT6grBRvIbhbdNS58Vu/uYXrP7NIc3TGbrTXThgsv
         8WoIe930ZIBADXV2Tmw7uCpwJrLCslDly0YHd04HLBMcgl4CghWpJJcSbKfvpR68oMcf
         5Yvw==
X-Gm-Message-State: AIkVDXI9Y65q+rCYLvTVHIyH2nZwT/YGFGzsoz+5hrnV04Xd7zKfQb6Z4MFuVBkvshx/iw==
X-Received: by 10.28.153.73 with SMTP id b70mr786478wme.14.1484206080193;
        Wed, 11 Jan 2017 23:28:00 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.28.166.7 with SMTP id p7ls126663wme.11.gmail; Wed, 11 Jan 2017
 23:27:59 -0800 (PST)
X-Received: by 10.223.170.7 with SMTP id p7mr6051345wrd.114.1484206079005;
        Wed, 11 Jan 2017 23:27:59 -0800 (PST)
Original-Received: from smtp.smtpout.orange.fr (smtp13.smtpout.orange.fr. [80.12.242.135])
        by mx.google.com with ESMTPS id p26si6516225wrp.311.2017.01.11.23.27.58
        for <std-proposals@isocpp.org>
        (version=TLS1 cipher=AES128-SHA bits=128/128);
        Wed, 11 Jan 2017 23:27:58 -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 ([86.214.89.68])
	by mwinf5d74 with ME
	id XKTx1u00M1UUyQN03KTxXT; Thu, 12 Jan 2017 08:27:58 +0100
X-ME-Helo: imac-de-vicente-botet-escriba.home
X-ME-Auth: dmljZW50ZS5ib3RldEB3YW5hZG9vLmZy
X-ME-Date: Thu, 12 Jan 2017 08:27:58 +0100
X-ME-IP: 86.214.89.68
In-Reply-To: <dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@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:30509
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/30509>

This is a multi-part message in MIME format.
--------------5F826F0C354AB6EF0BC1AF2B
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

Le 11/01/2017 =C3=A0 22:21, Nicol Bolas a =C3=A9crit :
> 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 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 =
:
>>>>
>>>>
>>>             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?
>>
>>
>>         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 representat=
ion.
>>                 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. The 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
>>     class`es use `int` by default), and there are enumerations that
>>     have an implied 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 need to know if it will fit within the range of an enum
>>     with an implied 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.
>
You have described very well the context.
> What goal are you trying to achieve with all this? Or more to the=20
> point, why are you incapable of simply giving the enum an underlying=20
> type and thus making the question moot?
Because the enum is declared in a 3pp library in C++98? or a common part=20
that is shared by an application using C++98 and another using C++2x?
>
>>     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 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 has effectively canonized it, so there it is.
>>     Alternatively, you may be using that enum as a bitfield.
>>
>>     The thing is, that is a solved problem: get the underlying type
>>     with `std::underlying_type_t<E>`. That, and its corresponding
>>     `numeric_limits` will tell you everything you need to know about
>>     the range of that enumeration.
>     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  solve this as well.
>>
>>     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?
>     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.
>>     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 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 case is any value between 0 and 8.
>
>
> But we can already answer that question. `X` is an `enum class`. As=20
> such, it /always/ has a fixed underlying type. If you don't specify=20
> one, then it shall be `int`, and therefore `X` can legally assume any=20
> `int` value.
 From the text of the standard I send before, the range is not the range=20
of int. Could you point me from where are you concluding this?
Is the same if the enum are not scoped?
>
> So the `std::underlying_type`-based solution will work fine.
>
> It should also be noted that the standard-specified range guarantees=20
> the ability to use an enum with an implied underlying type as a=20
> bitfield. That is, if you perform bitwise operations with the=20
> enumerators, the results are guaranteed to fit in the range. So you=20
> have nothing to worry about for that use case.
>
>>     If you don't have a problem to be solved with such a function,
>>     then 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 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=3D=
0x04,
>     ALL 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 the range of valid values?
>
>
> In that case, both have a forced underlying type, as I pointed out=20
> above. So the reason for the differing ranges of values is obvious.
>
> Now, let's assume you have revised your example to not use `enum=20
> class`. `enum X` does not have a fixed underlying type, so its range=20
> is determined by its enumerators. The reason that is different is=20
> because that's how it always was before, and there's terribly little=20
> reason to change it.
I'm not questioning the old C++98 behavior but the new C++11 behavior=20
(if we can say new for C++11)

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/0a4162ad-62ed-1c26-e210-81000402b193%40wanadoo.f=
r.

--------------5F826F0C354AB6EF0BC1AF2B
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 22:21, Nicol Bolas =
a
      =C3=A9crit=C2=A0:<br>
    </div>
    <blockquote
      cite=3D"mid:dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">On Wednesday, January 11, 2017 at 1:52: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 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.8ex;border-left:1px #ccc
                  solid;padding-left:1ex">
                  <div>
                    <div>Le 10/01/2017 =C3=A0 20:30, Nicol Bolas a =C3=A9cr=
it=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:1=
px
                          #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...@gmail.com</a>
                              a =C3=A9crit=C2=A0:<br>
                            </div>
                            <blockquote type=3D"cite">
                              <div dir=3D"ltr"><br>
                                <br>
                              </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>
                    <br>
                    =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"> <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-fam=
ily:'LMRoman10'">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-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">is
                                    the smallest enumerator and </span><spa=
n
style=3D"font-size:10.000000pt;font-family:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">is
                                    the largest, the values of the
                                    enumeration are the values in the
                                    range </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">to
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMMathItalic10'">K
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">be
                                    1 for a two=E2=80=99s complement
                                    representation and 0 for a ones=E2=80=
=99
                                    complement or sign-magnitude
                                    representation. </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">is
                                    the smallest value greater than or
                                    equal to </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">max</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'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">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-fam=
ily:'LMRoman10'">and
                                    equal to </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">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-fam=
ily:'LMMathSymbols10'">=E2=88=92
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">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-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">is
                                    zero if </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'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-fam=
ily:'LMRoman10'">is
                                    non-negative and </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathSymbols10'">=E2=88=92</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">+
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">K</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">) </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">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:'LMMathItalic10'">max</span><spa=
n
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">(</span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">M,</span><span
style=3D"font-size:10.000000pt;font-family:'LMRoman10'">1) </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">if
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">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-fam=
ily:'LMRoman10'">is
                                    zero and </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMMathItalic10'">M
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">+
                                    1 </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">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-fam=
ily:'LMRoman10';font-style:italic">enumerator-list
                                  </span><span
                                    style=3D"font-size:10.000000pt;font-fam=
ily:'LMRoman10'">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 th=
e
                    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 defin=
e
                    a class 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 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?</di=
v>
              </div>
            </blockquote>
            Because initializing the enum with an integer out of range
            is UB.<br>
          </div>
        </blockquote>
        <div><br>
          You're misunderstanding my question.<br>
          <br>
          The situation you describe is one where:<br>
          <br>
          1. You have an integer of arbitrary 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>
        </div>
      </div>
    </blockquote>
    You have described very well the context.<br>
    <blockquote
      cite=3D"mid:dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div>What goal are you trying to achieve with all this? Or more
          to the point, why are you incapable of simply giving the enum
          an underlying type and thus making the question moot?<br>
        </div>
      </div>
    </blockquote>
    Because the enum is declared in a 3pp library in C++98? or a common
    part that is shared by an application using C++98 and another using
    C++2x?<br>
    <blockquote
      cite=3D"mid:dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <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">
            <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'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'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 sol=
ve
            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'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'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 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, it <i>always</i> has a fixed underlying
          type. If you don't specify one, then it shall be `int`, and
          therefore `X` can legally assume any `int` value.<br>
        </div>
      </div>
    </blockquote>
    From the text of the standard I send before, the range is not the
    range of int. Could you point me from where are you concluding this?<br=
>
    Is the same if the enum are not scoped?<br>
    <blockquote
      cite=3D"mid:dbe0b3d3-e7ea-426a-a78d-6681202a4ea7@isocpp.org"
      type=3D"cite">
      <div dir=3D"ltr">
        <div><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 are guaranteed to
          fit in the range. So you have nothing to worry about for that
          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 bgcolor=3D"#FFFFFF" text=3D"#000000">
            <blockquote type=3D"cite">
              <div dir=3D"ltr">
                <div> 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 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=3D0x04, 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 that 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's assume you have revised your example to not use
          `enum class`. `enum X` does not have a fixed underlying type,
          so its range is determined by its enumerators. The reason that
          is different is because that's how it always was before, and
          there's terribly little reason to change it.<br>
        </div>
      </div>
    </blockquote>
    I'm not questioning the old C++98 behavior but the new C++11
    behavior (if we can say new for C++11)<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/0a4162ad-62ed-1c26-e210-81000402b193%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0a4162ad-62ed-1c26-e210-81000402b193=
%40wanadoo.fr</a>.<br />

--------------5F826F0C354AB6EF0BC1AF2B--

.
