2016-05-24 4 views
7

Der folgende Code braucht dringend : values(), zumindest in ideone zu kompilieren :: C++ 14:Warum muss ich ein nicht-statisches Array-Mitglied in einer Constexpr-Klasse initialisieren?

#include <iostream> 

template<int N> 
struct Table 
{ 
    constexpr Table() : values() 
    { 
     for (auto i = 0; i < N; ++i) 
     { 
      values[i] = i * i * i; 
     } 
    } 
    int values[N]; 
}; 

int main() { 
    constexpr auto a = Table<1000>(); 
    for (auto x : a.values) 
     std::cout << x << '\n'; 
} 

Aber warum? Ich hatte Gedanken entlang "Werte könnten auch in einer nicht-consExpr-Weise initialisiert werden und Werte() sagen explizit, dass wir sie in einer consExpr-konformen Weise initialisieren". Aber nicht : values() genauso klar weglassen?

+0

'clang' gibt eine seltsame Nachricht:' Zuordnung zu einem Objekt außerhalb seiner Lebensdauer ist nicht erlaubt in einem konstanten Ausdruck 'für die' = 'im Konstruktor von' Table' wenn ich 'values ​​()' weglasse. – Holt

+0

"Für den Konstruktor einer Klasse oder Struktur muss jedes Basisklassenunterobjekt und jeder nichtvariable nicht statische Datenmember initialisiert werden." – krOoze

+0

Aber es ist sowieso initialisiert, nur nicht explizit in jedem Fall. Es funktioniert für Nicht-Constexpr-Klassen – IceFire

Antwort

5

Betrachten Sie die Semantik.

Wenn Sie das Element aus der Initialisierungsliste auslassen, wird eine Standardinitialisierung durchgeführt, die in diesem Fall das Array mit nicht angegebenen Werten belässt. Das negiert den Zweck eines constexpr.

Der Wert, der das Array initialisiert, führt auf jedem Array-Element eine Null-Initialisierung durch (da dies ein Array von eingebauten Typen ist).

+0

das macht in der Tat Sinn und ich wusste nicht, dass – IceFire

+0

Warum ist es nicht erlaubt, die Elemente in der for-Schleife zu initialisieren? Danach haben alle Array-Elemente Werte –

+0

@ JohannesSchaub-litb, Zur Vereinfachung der Implementierung, denke ich. Gemessen an dem Zitat, das Serge unterstellt hat, mag das Komitee vielleicht denken, dass die c'tor-Kette weniger hartnäckig sein kann als das Verfolgen eines willkürlichen c'tor-Körpers. – StoryTeller

2

Einfach weil es Standard ist. Draft n4296 für aktuellen C++ Standard Zustände an:

7.1.5 Der constexpr Spezifizierer [dcl.constexpr] §4 (betonen mir):

4 Die Definition eines constexpr Konstruktor werden die folgenden Bedingungen erfüllen:
...

Außerdem entweder seine Funktion Körper wird sein = löschen, oder es werden die folgenden Bedingungen erfüllen:

(4.4) - entweder seine Funktionsstelle muss Standard sein = oder zusammengesetzte Aussage seiner f der Funktionskörper muss die Bedingungen für einen Funktionskörper einer consExpr-Funktion erfüllen;
(4.5) - Jedes nichtvariable nicht statische Datenelement und Basisklassenunterobjekt muss initialisiert werden (12.6.2);
...

+1

Vielleicht sollte der Standard wirklich klarstellen, dass die Standardinitialisierung nicht als "initialisiert" gilt. Ein unspezifizierter Wert sollte jedoch eigentlich kein "consxpr" sein, also folge ich logisch. – StoryTeller