Czy przyjmowanie adresu zmiennej lokalnej jest stałym wyrażeniem w C ++ 11?
Następujący program C ++ 11:
int x = 42;
void f()
{
int y = 43;
static_assert(&x < &y, "foo");
}
int main()
{
f();
}
Nie kompiluje się z gcc 4.7, ponieważ narzeka:
error: ‘&y’ is not a constant expression
Zgodziłoby się to z moją intuicją. Adresy
potencjalnie zmienia się przy każdym wywołaniuf
, więc oczywiście nie można go obliczyć podczas tłumaczenia.
Jednak żaden z punktów wypunktowanych w 5.19 [expr.const] nie wyklucza, by był stałym wyrażeniem.
Widzę tylko dwóch pretendentów:
konwersja wartości na wartość r ...
ale jeśli się nie mylę (?), w programie nie ma konwersji do wartości lvalue-to-rvalue.
I
naid-expression
która odnosi się do zmiennej [snip], chyba że:
któryy
jest - jest inicjowany stałym wyrażeniem43
.
Czy to błąd w standardzie, czy coś mi brakuje?
Aktualizacja:
To zagmatwane jak diabli, ale myślę, że jestem na szczycie, więc pokażę przykład, który pokaże, co się dzieje:
int x = 42;
void f()
{
int y = 43;
// address constant expressions:
constexpr int* px = &x; // OK
constexpr int* py = &y; // ERROR: pointer context for local variable
// boolean constant expressions:
constexpr bool bx = &x; // OK
constexpr bool by = &y; // OK
// comparison constant expressions:
constexpr bool eq = (&x == &y); // OK
constexpr bool lt = (&x < &y); // ERROR: undefined behaviour disqualifies
a constant expression
}
int main()
{
f();
}
Najpierw rozróżnij stałe wyrażenie podstawowe (5.19p2) od wyrażenia stałego (5.19p4). Specyficznie wyrażenia stałe wyrażenia stałego muszą być tylko stałymi wyrażeniami podstawowymi, a nie wyrażeniami stałymi. Oznacza to, że bycie stałym wyrażeniem jest właściwością pełnego wyrażenia, a nie podwyrażeń. Ponadto wymaga spojrzenia na kontekst, w którym używane jest pełne wyrażenie.
Jak się okazuje, błąd gcc jest mylący. po pierwsze&y
może być stałym wyrażeniem w niektórych kontekstach. Po drugie, powód&x < &y
nie jest stałym wyrażeniem z powodu porównania niepowiązanych wskaźników, a nie podwyrażenia&y
.