Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!uupsi!sunic!chalmers.se!appli!niklas From: niklas@appli.se (Niklas Hallqvist) Newsgroups: comp.lang.c++ Subject: Re: structures with variable length elements. Message-ID: <1385@appli.se> Date: 21 May 91 17:43:35 GMT References: <1991May18.010928.16619@cshl.org> <736@taumet.com> Organization: Applitron Datasystem AB, GOTHENBURG, SWEDEN Lines: 74 steve@taumet.com (Stephen Clamage) writes: >monardo@cshl.org (Pat Monardo) writes: >>i am only superficially aware of C++, so.... >>i recall that PL1 would allow a structure to contain variable length >>elements (depending on a length parameter). With C i would >>have to declare a pointer and allocate the memory. >>Did PL1 allocate the vector inline? Does C++ do this? >There is a "trick" in C to make variable-length structures: > struct phony { > ... > int i[1]; /* must be last field in the struct */ > }; >Then you create an instance like > phony *p = (phony*)malloc(sizeof(phony) + 511*sizeof(int)); >getting a version of a phony with an array of 512 ints at element 'i'. >This is very poor programming practice, in my view. >Another way, which also works in C++, is to make 'i' a pointer, then >allocate an array for 'i' to point to whenever you create an instance of >the struct. Then the order of the fields doesn't matter. In C, this >technique requires some careful bookkeeping, but in C++ it all goes in >the constructor and destructor, and you don't have to worry about it >in the rest of the code. > class var_int { > ... > int *ip; > int array_size; // size of the ip array > public: > var_int(int sz); // constructor allocates array of sz ints > ~var_int(); // destructor deallocates the array > size(); // return number of elements > int& operator[](int index); // access array element > }; In a C++ compiler supporting templates the extra new-delete pair can go away, if the size of the buffer is known at compile time. Consider: class var_int_base { ... int* ip; int array_size; public: var_int_base(int* vec, int sz) : ip(vec), array_size(sz) {} int size() { return array_size }; int& operator[](int index) { return ip[index]; } }; template class var_int : var_int_base { int buf[size]; public: var_int(int sz) : var_int_base(buf, sz) {}; }; void foo() { var_int<256> vec256; var_int<128> vec128; // and if you want to treat them as if they were of the same type, use: var_int_base* vecp; vecp = &vec256; vecp = &vec128; } The code above has NOT been tested, but I think it explains the idea even if it might be slightly incorrect. I would use references instead of pointers, if I were sure of the semantics of references to arrays passed as parameters, which I'm not for the moment. Maybe I'll test this tonight... In real life the element type should of course be a template argument too. Niklas