Topic: lvalue-to-rvalue conversions in constant expressions


Author: Pavel Minaev <int19h@gmail.com>
Date: Wed, 25 May 2011 01:09:45 CST
Raw View
On Apr 27, 9:52 am, Nikolay Ivchenkov<ts...@mail.ru> wrote:
> According to N3290 - 5.19 [expr.const] p.2,
>
>      A conditional-expression is a core constant expression unless it
> involves one of the following as a potentially evaluated subexpression
> (3.2) [...]:
>
>      - an lvalue-to-rvalue conversion (4.1) unless it is applied to
>          - a glvalue of integral or enumeration type that refers to a
> non-volatile const object with a preceding initialization, initialized
> with a constant expression, or
>          - a glvalue of literal type that refers to a non-volatile
> object defined with constexpr, or that refers to a sub-object of such
> an object, or
>          - a glvalue of literal type that refers to a non-volatile
> temporary object whose lifetime has not ended, initialized with a
> constant expression;
>
> Does this wording mean that all initializers below are correct?
>
>      constexpr int arr[2] = { 1, 2 };
>      constexpr int const *p =&arr[0];
>      constexpr int const *const *pp =&p;
>
>      constexpr int const volatile *pv =&arr[0];
>
>      enum
>      {
>          // is this well-formed?
>          e1 = *(arr + 1),
>
>          // is this well-formed?
>          e2 = **pp,
>
>          // is this well-formed?
>          e3 = *pv
>      };

In addition to that, I would like to know if this is well-formed:

   e1 = *("abc" + 1);

i.e. whether a string literal is a "non-volatile const object with a
preceding initialization, initialized with a constant expression".


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Johannes Schaub <schaub.johannes@googlemail.com>
Date: Thu, 26 May 2011 10:20:44 CST
Raw View
Pavel Minaev wrote:

>
> On Apr 27, 9:52 am, Nikolay Ivchenkov<ts...@mail.ru> wrote:
>> According to N3290 - 5.19 [expr.const] p.2,
>>
>>      A conditional-expression is a core constant expression unless it
>> involves one of the following as a potentially evaluated subexpression
>> (3.2) [...]:
>>
>>      - an lvalue-to-rvalue conversion (4.1) unless it is applied to
>>          - a glvalue of integral or enumeration type that refers to a
>> non-volatile const object with a preceding initialization, initialized
>> with a constant expression, or
>>          - a glvalue of literal type that refers to a non-volatile
>> object defined with constexpr, or that refers to a sub-object of such
>> an object, or
>>          - a glvalue of literal type that refers to a non-volatile
>> temporary object whose lifetime has not ended, initialized with a
>> constant expression;
>>
>> Does this wording mean that all initializers below are correct?
>>
>>      constexpr int arr[2] = { 1, 2 };
>>      constexpr int const *p =&arr[0];
>>      constexpr int const *const *pp =&p;
>>
>>      constexpr int const volatile *pv =&arr[0];
>>
>>      enum
>>      {
>>          // is this well-formed?
>>          e1 = *(arr + 1),
>>
>>          // is this well-formed?
>>          e2 = **pp,
>>
>>          // is this well-formed?
>>          e3 = *pv
>>      };
>
> In addition to that, I would like to know if this is well-formed:
>
>    e1 = *("abc" + 1);
>
> i.e. whether a string literal is a "non-volatile const object with a
> preceding initialization, initialized with a constant expression".
>

What you need to check is not whether the string literal suffices that
description, but whether the second character of it does.

The character is a const object. The question remains is what "preceeding
initialization" means in this context. The spec says:

"After translation phase 6, a string literal that does not begin with an
encoding-prefix is an ordinary string literal, and is initialized with the
given characters. [...] A narrow string literal has type "array of n const
char", where n is the size of the string as defined below, and has static
storage duration."

This doesn't state whether the character is considered to have a "preceeding
initialization" with regard to the read in the constant expression. FWIW,
GCC accepts this use.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Nikolay Ivchenkov<tsoae@mail.ru>
Date: Wed, 27 Apr 2011 10:52:51 CST
Raw View
According to N3290 - 5.19 [expr.const] p.2,

     A conditional-expression is a core constant expression unless it
involves one of the following as a potentially evaluated subexpression
(3.2) [...]:

     - an lvalue-to-rvalue conversion (4.1) unless it is applied to
         - a glvalue of integral or enumeration type that refers to a
non-volatile const object with a preceding initialization, initialized
with a constant expression, or
         - a glvalue of literal type that refers to a non-volatile
object defined with constexpr, or that refers to a sub-object of such
an object, or
         - a glvalue of literal type that refers to a non-volatile
temporary object whose lifetime has not ended, initialized with a
constant expression;

Does this wording mean that all initializers below are correct?

     constexpr int arr[2] = { 1, 2 };
     constexpr int const *p =&arr[0];
     constexpr int const *const *pp =&p;

     constexpr int const volatile *pv =&arr[0];

     enum
     {
         // is this well-formed?
         e1 = *(arr + 1),

         // is this well-formed?
         e2 = **pp,

         // is this well-formed?
         e3 = *pv
     };

     struct X
     {
         unsigned char a;
         int b;
         unsigned char c;
     };

     constexpr X x = { 1, 2, 3 };

     enum
     {
         // is this well-formed?
         e4 = (&x.a)[offsetof(X, c) - offsetof(X, a)],

         // is this well-formed?
         e5 = (&x.a)[offsetof(X, b) - offsetof(X, a)]
     };


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]