2015-12-21 3 views
1

Если я определяю структуры на уровне модуля, я могу ссылаться на еще не определенные структуры.Порядок объявления структуры

struct S { 
    ComesLater c; 
} 
struct ComesLater {} 

Но если я сделать то же самое внутри unittest или функционального блока, он не работает:

unittest { 
    struct S { 
    ComesLater c; 
    } 
    struct ComesLater {} 
} 

Error: undefined identifier 'ComesLater'

Почему? Как я могу получить независимые от заказа объявления внутри функций? Есть ли какая-то декларация вперед в d? Мне нужно это, потому что я сгенерирую структуры с помощью mixin и упорядочивая объявления в порядке их внутренних зависимостей, было бы довольно сложным, а иногда и невозможным, если бы существовали циркулярные ссылки на структуры. (с использованием указателей.)

ответ

2

Декларации внутри функций, unittests или где-либо еще, что эти операторы действительно могут быть выполнены, действительно зависят от заказа, потому что их значения могут зависеть от кода перед их запуском. Подумайте о местной переменной:

int a; 
writeln(a); 
a = b; 
int b = get_user_line(); 

Если заказ не важен там, когда будут вызваны две функции? Будет ли у пользователя запрашиваться строка перед записью, когда декларации будут переписаны?

Текущее поведение, связанное с получением неопределенной переменной переменной, делает ее простой и понятной.

Он работает независимо от порядка в других контекстах, потому что не существует исполняемого кода, на котором он может зависеть, поэтому нет никакого поведения, которое может измениться, если компилятор должен думать о нем по-другому.

Итак:

Как я могу получить заказ независимые объявления внутри функции?

Измените контекст так, чтобы не было исполняемого кода ... вставьте его внутри другой структуры!

void main() { // or unittest { } 
     struct Holder { 
       static struct S { 
         C c; 
       } 
       static struct C {} 
     } 
} 

Поскольку исполнение происходит вокруг держателя и не происходит внутри него, порядок декларирования внутри не имеет значения. Поскольку вы можете определить почти что-либо внутри структуры, вы можете использовать это для переменных, функций, других структур и т. Д. В основном все, что вам нужно сделать, это обернуть существующий код внутри скобок struct Holder {}.

Сделав все, что находится внутри, вы можете просто использовать его, как контейнер, и ссылаться на вещи с помощью Holder.S и т. Д., Снаружи.

+0

Ницца! Боюсь, я не смогу использовать это обходное решение, потому что я мог бы генерировать несколько блоков таких структур внутри одной области, и это работает только один раз. (Тогда Holder будет уже определен.) Разве нет никакой возможности, чтобы вы могли получить какую-то декларацию вперед? Или определить блок кода, который не имеет порядка выполнения внутри, но не меняет текущую область? (Подобно Holder.) – Tamas

+2

Я смог поместить структуры внутри шаблона mixin Foo() {static struct S {C c; } static struct C {}} ', тогда вызов' mixin Foo!(); 'Затем я получаю независимый блок заказа без дополнительного держателя! =) – Tamas

+0

Ну, вы всегда можете изменить имя при каждом его создании. Holder, Lynch, Mukasey, Gonzales :) или Holder1, Holder2. Трюк __LINE__ может помочь вам создавать уникальные имена внутри кода генерации строки mixin.Вы также можете попытаться сделать держателем «mixin template» вместо «struct», а затем смешать его сразу после объявления, чтобы его символы вводились в родительскую область. –

Смежные вопросы