Есть задача - инициализировать массив структур:
typedef struct { const double *inputs, *outputs; } Example;
где inputs и outputs - указатели на массивы даблов, произвольной длины, терминированные NaN.
Хочется это сделать без лишнего оверхеда, без использования кучи и всяких разных рантайм костылей.
Пока что пришел к такому варианту:
#include <stdio.h>
#include <math.h>
#define INIT_LIST(type, ...) ((const type[]){__VA_ARGS__})
#define DOUBLES(...) INIT_LIST(double, __VA_ARGS__, (double)NAN)
#define INIT_STRUCT_PTR(type, ...) (&(type){__VA_ARGS__})
#define EXAMPLE(...) INIT_STRUCT_PTR(Example, __VA_ARGS__)
typedef struct { const double *inputs, *outputs; } Example;
// NAN-terminated array of doubles
void printDoubles(const char *fmt, const double *nandedArray) {
while(!isnan(*nandedArray)) {
printf(fmt, *nandedArray++); // не секурно, зато удобно
}
}
#define TAB " "
// NULL-terminated array of examples
void printExamples(Example **examples) {
for( ; *examples; ++examples) {
printf("Example {\n" TAB "inputs {\n");
printDoubles(TAB TAB "%f\n", (*examples)->inputs);
printf(TAB "}\n" TAB "outputs {\n");
printDoubles(TAB TAB "%f\n", (*examples)->outputs);
printf(TAB "}\n}\n");
}
}
int main() {
Example *examples[] = {
EXAMPLE(DOUBLES(1.23), DOUBLES(4.56, 7.89)),
EXAMPLE(DOUBLES(10.11, 12.13), DOUBLES(14.15)),
NULL
};
printExamples(examples);
}
Example {
inputs {
1.230000
}
outputs {
4.560000
7.890000
}
}
Example {
inputs {
10.110000
12.130000
}
outputs {
14.150000
}
}
В плюсовом коде я бы запилил вектор векторов и инициализировал бы его через initializer_list. Поэтому, оказавшись без столь удобных инструментов, я немного впал в ступор.
Какие есть еще варианты?