Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 1076639
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T21:27:27+00:00 2026-05-16T21:27:27+00:00

I’ve written the rudiments of a class for creating dynamic structures in C++. Dynamic

  • 0

I’ve written the rudiments of a class for creating dynamic structures in C++. Dynamic structure members are stored contiguously with (as far as my tests indicate) the same padding that the compiler would insert in the equivalent static structure. Dynamic structures can thus be implicitly converted to static structures for interoperability with existing APIs.

Foremost, I don’t trust myself to be able to write Boost-quality code that can compile and work on more or less any platform. What parts of this code are dangerously in need of modification?

I have one other design-related question: Is a templated get accessor the only way of providing the compiler with the requisite static type information for type-safe code? As it is, the user of dynamic_struct must specify the type of the member they are accessing, whenever they access it. If that type should change, all of the accesses become invalid, and will either cause spectacular crashes—or worse, fail silently. And it can’t be caught at compile time. That’s a huge risk, and one I’d like to remedy.

Example of usage:

struct Test {

    char a, b, c;
    int i;
    Foo object;

};

void bar(const Test&);

int main(int argc, char** argv) {

    dynamic_struct<std::string> ds(sizeof(Test));

    ds.append<char>("a") = 'A';
    ds.append<char>("b") = '2';
    ds.append<char>("c") = 'D';
    ds.append<int>("i") = 123;
    ds.append<Foo>("object");
    bar(ds);

}

And the code follows:

//
// dynamic_struct.h
//
// Much omitted for brevity.
//


/**
 * For any type, determines the alignment imposed by the compiler.
 */
template<class T>
class alignment_of {
private:

    struct alignment {

        char a;
        T b;

    }; // struct alignment

public:

    enum { value = sizeof(alignment) - sizeof(T) };

}; // class alignment_of


/**
 * A dynamically-created structure, whose fields are indexed by keys of
 * some type K, which can be substituted at runtime for any structure
 * with identical members and packing.
 */
template<class K>
class dynamic_struct {
public:


    // Default maximum structure size.
    static const int DEFAULT_SIZE = 32;


    /**
     * Create a structure with normal inter-element padding.
     */
    dynamic_struct(int size = DEFAULT_SIZE) : max(size) {

        data.reserve(max);

    } // dynamic_struct()


    /**
     * Copy structure from another structure with the same key type.
     */
    dynamic_struct(const dynamic_struct& structure) :
        members(structure.members), max(structure.max) {

        data.reserve(max);

        for (iterator i = members.begin(); i != members.end(); ++i)
            i->second.copy(&data[0] + i->second.offset,
                &structure.data[0] + i->second.offset);

    } // dynamic_struct()


    /**
     * Destroy all members of the structure.
     */
    ~dynamic_struct() {

        for (iterator i = members.begin(); i != members.end(); ++i)
            i->second.destroy(&data[0] + i->second.offset);

    } // ~dynamic_struct()


    /**
     * Get a value from the structure by its key.
     */
    template<class T>
    T& get(const K& key) {

        iterator i = members.find(key);

        if (i == members.end()) {

            std::ostringstream message;
            message << "Read of nonexistent member \"" << key << "\".";
            throw dynamic_struct_access_error(message.str());

        } // if

        return *reinterpret_cast<T*>(&data[0] + i->second.offset.offset);

    } // get()


    /**
     * Append a member to the structure.
     */
    template<class T>
    T& append(const K& key, int alignment = alignment_of<T>::value) {

        iterator i = members.find(key);

        if (i != members.end()) {

            std::ostringstream message;
            message << "Add of already existing member \"" << key << "\".";
            throw dynamic_struct_access_error(message.str());

        } // if

        const int modulus = data.size() % alignment;
        const int delta = modulus == 0 ? 0 : sizeof(T) - modulus;

        if (data.size() + delta + sizeof(T) > max) {

            std::ostringstream message;

            message << "Attempt to add " << delta + sizeof(T)
                << " bytes to struct, exceeding maximum size of "
                << max << ".";

            throw dynamic_struct_size_error(message.str());

        } // if

        data.resize(data.size() + delta + sizeof(T));

        new (static_cast<void*>(&data[0] + data.size() - sizeof(T))) T;

        std::pair<iterator, bool> j = members.insert
            ({key, member(data.size() - sizeof(T), destroy<T>, copy<T>)});

        if (j.second) {

            return *reinterpret_cast<T*>(&data[0] + j.first->second.offset);

        } else {

            std::ostringstream message;
            message << "Unable to add member \"" << key << "\".";
            throw dynamic_struct_access_error(message.str());

        } // if

    } // append()


    /**
     * Implicit checked conversion operator.
     */
    template<class T>
    operator T&() { return as<T>(); }


    /**
     * Convert from structure to real structure.
     */
    template<class T>
    T& as() {

        // This naturally fails more frequently if changed to "!=".
        if (sizeof(T) < data.size()) {

            std::ostringstream message;

            message << "Attempt to cast dynamic struct of size "
                << data.size() << " to type of size " << sizeof(T) << ".";

            throw dynamic_struct_size_error(message.str());

        } // if

        return *reinterpret_cast<T*>(&data[0]);

    } // as()


private:


    // Map from keys to member offsets.
    map_type members;

    // Data buffer.
    std::vector<unsigned char> data;

    // Maximum allowed size.
    const unsigned int max;


}; // class dynamic_struct
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-16T21:27:27+00:00Added an answer on May 16, 2026 at 9:27 pm

    There’s nothing inherently wrong with this kind of code. Delaying type-checking until runtime is perfectly valid, although you will have to work hard to defeat the compile-time type system. I wrote a homogenous stack class, where you could insert any type, which functioned in a similar fashion.

    However, you have to ask yourself- what are you actually going to be using this for? I wrote a homogenous stack to replace the C++ stack for an interpreted language, which is a pretty tall order for any particular class. If you’re not doing something drastic, this probably isn’t the right thing to do.

    In short, you can do it, and it’s not illegal or bad or undefined and you can make it work – but you only should if you have a very desperate need to do things outside the normal language scope. Also, your code will die horrendously when C++0x becomes Standard and now you need to move and all the rest of it.

    The easiest way to think of your code is actually a managed heap of a miniature size. You place on various types of object.. they’re stored contiguously, etc.

    Edit: Wait, you didn’t manage to enforce type safety at runtime either? You just blew compile-time type safety but didn’t replace it? Let me post some far superior code (that is somewhat slower, probably).

    Edit: Oh wait. You want to convert your dynamic_struct, as the whole thing, to arbitrary unknown other structs, at runtime? Oh. Oh, man. Oh, seriously. What. Just no. Just don’t. Really, really, don’t. That’s so wrong, it’s unbelievable. If you had reflection, you could make this work, but C++ doesn’t offer that. You can enforce type safety at runtime per each individual member using dynamic_cast and type erasure with inheritance. Not for the whole struct, because given a type T you can’t tell what the types or binary layout is.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.