Вопрос как всегда в том, что у нас дефолтный уровень и что мы эскейпим. Дефолтным уровнем всегда должно быть то, чего больше, что более по-существу важно при чтении. А это в зависимости от задачи может быть как метакод, так и рантаймкод. В теле макроса дефолтный уровень код макроса, а генерируемый код инклюдится в виде квазицитат. В темплейтах наоборот дефолтный уровень target-код, а метакод эскейпится словом static. Шош тут делать, разные задачи элегантнее делать по-разному. Ту, что ты привёл выше, темплейтами делать элегантнее. Естественно, тривиальные с точки зрения алгоритмики макросов задачи темплейтами делать кошерно и красиво
( ... )
Это все вопрос исключительно выразительности макросистемы. Если можно раскрываться в макросы и квазицитаты, то можно сделать альтернативные макро-объявления, в которых дефолтным уровнем будет уровень рантайма.
D не одним static if богат, там и "два вложенных цикла, да рекурсийка, да..." так же просто делаются. TypeTuple, раскрываемый в статике foreach по ним, рекурсивные шаблонные ф-ии и исполнение почти произвольного чистого кода при компиляции - это вам не старинные плюсовые темплейты.
а что будет, если R *тоже* зависит от каких-то членов или методов MyRange(R) напрямую или через цепочку типов? (в шаблонах плюсов у нас порядок в данном случае задается вручную (путем включения куда-то forward declaration, а куда-то полных деклараций), а в Д как?)
пример высосан из пальца (в смысле, я не буду рассказывать, зачем такое может потребоваться на практике)
пусть у нас есть классы X и Y
нам нужно, чтобы при наличии в классе X поля x в классе Y появлялись определенные поля и метод foo, а при наличии в классе Y поля y в классе X появлялись определенные поля и метод bar
при этом очень желательно, но не обязательно, указать что X зависит от Y, а Y зависит от X - полностью это указать не получится, т.к. полная запись будет что-то вроде X>>> и никогда не закончится
А, хороший вопрос. Порядок объявлений в D не важен, и вот такой код компилится:
class X { int x; static if (hasMember!(Y, "y")) bool bar; }
class Y { string y; //static if (hasMember!(X, "x")) // byte foo; }
Но если раскомментировать вторую проверку, то перестает, не осиливает такую явную циклическую зависимость. Возможно, какой-нибудь трюк с наследованием или хитрыми шаблонами поможет, но сходу не назову.
enum s = import("file.xml"); // compile time string constant Потом берешь Pegged и парсишь https://github.com/PhilippeSigaud/Pegged он в компайлтайме умеет применять только что описанные (в том же файле) грамматики.
Reply
Reply
Reply
Reply
Reply
Reply
пусть у нас есть классы X и Y
нам нужно, чтобы при наличии в классе X поля x в классе Y появлялись определенные поля и метод foo, а при наличии в классе Y поля y в классе X появлялись определенные поля и метод bar
при этом очень желательно, но не обязательно, указать что X зависит от Y, а Y зависит от X - полностью это указать не получится, т.к. полная запись будет что-то вроде X>>> и никогда не закончится
Reply
class X {
int x;
static if (hasMember!(Y, "y"))
bool bar;
}
class Y {
string y;
//static if (hasMember!(X, "x"))
// byte foo;
}
Но если раскомментировать вторую проверку, то перестает, не осиливает такую явную циклическую зависимость. Возможно, какой-нибудь трюк с наследованием или хитрыми шаблонами поможет, но сходу не назову.
Reply
Reply
enum s = import("file.xml"); // compile time string constant
Потом берешь Pegged и парсишь
https://github.com/PhilippeSigaud/Pegged
он в компайлтайме умеет применять только что описанные (в том же файле) грамматики.
Reply
а чуть подробнее?
Reply
Leave a comment