2015-02-19 11 views
17

Próbuję zainicjować odniesienie constexpr bez powodzenia. Próbowałemsposób inicjowania odwołania do obiektu constexpr

#include <iostream> 

constexpr int& f(int& x) // can define functions returning constexpr references 
{ 
    return x; 
} 

int main() 
{ 
    constexpr int x{20}; 
    constexpr const int& z = x; // error here 
} 

ale Dostaję błąd czasu kompilacji

error: constexpr variable 'z' must be initialized by a constant expression

upuszczenie const wyników w

error: binding of reference to type 'int' to a value of type 'const int' drops qualifiers

choć miałem wrażenie, że constexpr automatycznie implikuje const dla zmiennej deklaracje.

Więc moje pytania to:

  1. Czy constexpr referencje kiedykolwiek przydatne? (tj. "lepsze" niż odniesienia const)
  2. Jeśli tak, jak mogę je skutecznie zdefiniować?

PS: Widziałem kilka pytań związanych z moim, takich jak Which values can be assigned to a `constexpr` reference?, ale nie sądzę, że odpowiadają na moje pytania.

Odpowiedz

19
  1. Are constexpr references ever useful? (i.e., "better" than const references)

są gwarantowane one być initiailized przed rozpoczęciem programu, natomiast odniesienie do const można zainicjować podczas dynamicznej inicjalizacji po uruchomieniu program uruchomiony.

  1. If yes, how can I effectively define them?

constexpr odniesienia musi wiązać się globalnym, a nie zmiennej lokalnej (lub bardziej formalnie, musi wiązać się z czymś statycznym okres przechowywania).

Odwołanie jest koncepcyjnie równoznaczne z zajęciem adresu zmiennej, a adres zmiennej lokalnej nie jest stałą (nawet w main, która może być wywołana tylko raz, więc jej zmienne lokalne są inicjowane tylko raz).

+0

Ahh, ok, dzięki! Działa, jeśli przeniesię 'x' poza' main() '. Dlaczego jednak muszę umieścić dodatkową 'const' w definicji' z'? – vsoftco

+7

Muszą wiązać się z czymś ze statycznym czasem przechowywania, który może być lokalnym "statycznym" lub globalnym. –

+0

@ T.C., Tak, jeśli zrobię to statycznie (wewnątrz głównego), działa również. – vsoftco

8

Tak więc problem jest taki, że constexpr odniesienia musi wiązać się z obiektem statycznym czas przechowywania, które są omówione w rozdziale draft C++11 standard: N33375.19[expr.const] (nacisk kopalni):

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function

draft C++14 standard: N3936 zmienia brzmienie:

A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration or to a function, or a prvalue core constant expression whose value is an object where, for that object and its subobjects:

  • each non-static data member of reference type refers to an object with static storage duration or to a function, and
  • if the object or subobject is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.

więc zmiana deklarację x jak tak będzie działać:

constexpr static int x{20}; 
5

Jak T.C. mówi inicjatora musi być obiektem ze statycznym czas przechowywania.

N4140/§5.19/4 A constant expression is either a glvalue core constant expression whose value refers to an object with static storage duration [...]

N4140/§7.1.5/9 A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. [...] Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression.

W N3337 sformułowanie jest inne.