Я экспериментировал с использованием рекурсии шаблона для создания вложенных структур POD, и я наткнулся на какое-то поведение, которого я не ожидал. Вот упрощенный тест:Инициализация templated, recursive, POD struct
#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;
}
Я ожидал бы этот код выхода
5
5
В самом деле, что это то, что создается при компиляции с GCC 4.8.4 и 5.1.
Однако компиляции либо с Clang (3.5 или 3.7) или Visual Studio 2010, а не приводит к
5
0
Является ли мой код или мое понимание этого плохого в некотором роде, или сделать Clang и Visual Studio как-то так есть ошибки, которые приводят к тому же ошибочному результату?
Если я неправильно понял, я не думаю, что эта заметка будет применяться здесь. Я понимаю, что неопределенная инициализация применяется к динамической инициализации. То есть инициализация происходит при запуске программы. Насколько я понимаю, причина, по которой данный пример не определен, заключается в том, что 'fd()' может или не может быть встроен компилятором, поэтому 'd1' может быть динамически или статически инициализирован, поэтому' d2' не указан. В моем случае все это const POD, поэтому все должно быть статически инициализировано. – rkjnsn
Это может быть неуказанное поведение, но если это так, я не думаю, что это справочная нота, которая делает это так. – rkjnsn
@rkjnsn Статическая инициализация требует инициализации с постоянным выражением - поэтому некоторые из ваших объектов динамически инициализируются. – Barry