Ich experimentierte mit Vorlagen Rekursion, um eine verschachtelte POD-Strukturen zu generieren, und ich stieß auf etwas Verhalten, das ich nicht erwartet hatte. Hier ist ein vereinfachtes Testfall:Initialisieren templated, rekursive, POD-Struktur
#include <cstddef>
template<std::size_t size>
struct RecursiveStruct {
public:
template <std::size_t start, std::size_t length>
struct Builder {
static const Builder value;
static const size_t mid = start + length/2;
static const size_t end = start + length;
Builder<start, mid - start> left;
Builder<mid, end - mid> right;
};
template <std::size_t start>
struct Builder<start, 1> {
static const Builder value;
int data;
};
static const Builder<0, size> result;
};
template<std::size_t size>
const typename RecursiveStruct<size>::template Builder<0, size>
RecursiveStruct<size>::result = Builder<0, size>::value;
template<std::size_t size>
template<std::size_t start, std::size_t length>
const typename RecursiveStruct<size>::template Builder<start, length>
RecursiveStruct<size>::Builder<start, length>::value
= { Builder<start, mid - start>::value, Builder<mid, end - mid>::value };
template<std::size_t size>
template <std::size_t start>
const typename RecursiveStruct<size>::template Builder<start, 1>
RecursiveStruct<size>::Builder<start, 1>::value = { 5 };
////////////////////////////////////////////////////////
#include <iostream>
using std::cout;
using std::endl;
using std::size_t;
int main() {
cout << RecursiveStruct<1>::result.data << endl;
cout << RecursiveStruct<2>::result.left.data << endl;
return 0;
}
Ich würde erwarten, diesen Code zur Ausgabe
5
5
der Tat, dass es, was erzeugt wird, wenn ich mit GCC 4.8.4 und 5.1 zu kompilieren.
jedoch Kompilieren entweder mit Clang (3.5 oder 3.7) oder Visual Studio 2010 führt stattdessen in
5
0
Ist mein Code oder mein Verständnis davon falsch in irgendeiner Weise, oder tun Clang und Visual Studio irgendwie beide haben Fehler, die zu der gleichen fehlerhaften Ausgabe führen?
Wenn ich nicht falsch verstanden habe, glaube ich nicht, dass dieser Hinweis hier gelten würde. Nach meinem Verständnis gilt für die dynamische Initialisierung eine undefinierte Initialisierung. Das heißt, Initialisierung beim Programmstart. Wie ich es verstehe, ist der Grund dafür, dass das angegebene Beispiel nicht definiert ist, weil 'fd()' vom Compiler inline sein kann oder nicht, daher kann "d1" entweder dynamisch oder statisch initialisiert werden, weshalb "d2" nicht spezifiziert ist. In meinem Fall ist alles const POD, also sollte alles statisch initialisiert werden. – rkjnsn
Es kann immer noch unspezifisches Verhalten sein, aber wenn dem so ist, glaube ich nicht, dass es der Referenzhinweis ist, der es so macht. – rkjnsn
@rkjnsn Die statische Initialisierung erfordert, dass sie mit einem konstanten Ausdruck initialisiert wird - so dass einige Ihrer Objekte dynamisch initialisiert werden. – Barry