Basic problem
I'm in a tricky situation that requires taking a pointer to a struct mainset
and turning this into a pointer to a struct subset
, whose fields are a contiguous subset of the fields of mainset
, starting from the first. Is such a thing possible, with well-defined behavior? I realize that this is a pretty terrible thing to do, but I have good and frustrating reasons to do it [explained at the bottom for patient readers].
My attempt an an implementation seems to work, on OS X with the clang compiler:
#include <iostream>
struct mainset {
size_t size;
uint32_t reflex_size;
};
struct subset {
size_t size;
};
using namespace std;
int main(int argc, char *argv[]) {
mainset test = {1, 1};
subset* stest = reinterpret_cast<subset*>(&test);
std::cout << stest->size << std::endl;
}
The output is indeed 1, as I expect. However, I wonder: am I just getting lucky with a particular compiler and a simple case (in reality my structs are more complicated), or will this work in general?
Explanation of why I have to do this
My project uses the GSL library for linear algebra. This library makes use of structs of the form
struct gsl_block {
size_t size;
double* data;
}
and similar structs like gsl_vector
and gsl_matrix
. So, I've used these structs as members of my C++ classes; no problem. A recently demanded feature for my project, however, is to enable reflection to my classes with the Reflex tool, part of the ROOT ecosystem. To enable reflexion for a struct like this in Reflex, I must add an annotations like
struct gsl_block {
size_t size;
double* data; //[size]
}
This annotation tells Reflex that that the length of the array is provided by the field size
of the same struct. Normally that would be that, but Reflex and ROOT have a very unfortunate limitation: the length field must be 32 bit. Having been informed that this limitation won't be fixed anytime soon, and not having the time/resources to fix it myself, I'm looking for workarounds. My idea is to somehow embed a struct bit-compatible with gsl_block
within a larger struct:
struct extended_gsl_block {
uint32_t reflex_size;
size_t size;
double* data; //[reflex_size]
}
and similar things for gsl_vector
and gsl_matrix
; I can ensure that reflex_size
and size
are always equal (neither is ever bigger than ~50) and Reflex will be able to parse this header correctly. Since GSL routines work with pointers to these structs, my idea is this: given a pointer extended_gsl_block*
, somehow get a pointer to just the fields size
and data
and reinterpret_cast
this into a gsl_block*
.
Aucun commentaire:
Enregistrer un commentaire