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 ]