Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. Implementing many-to-many relationships
Forum Update on Monday, May 27th 2025

Implementing many-to-many relationships

Scheduled Pinned Locked Moved Solved Brainstorm
40 Posts 8 Posters 10.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • kshegunovK kshegunov

    @TomZ said in Implementing many-to-many relationships:

    Sure you can use weak pointers (or qpointers, or shared pointers), but that just uses more cycles to zero the pointers.

    Cycles pretty much irrelevant in business code, I much rather rely on the prefetcher being smart enough to build its heuristic (which it really is!). The only place it truly matters is whenever you're low-level optimizing a hot codepath, like in a heavy calculation. I'd take the additional indirection any day if I can maintain the code more easily in the long-run, which is the typical case for business logic (which appears to be the case here).

    TomZT Offline
    TomZT Offline
    TomZ
    wrote on last edited by
    #29

    @kshegunov said in Implementing many-to-many relationships:

    Cycles pretty much irrelevant in business code

    you can waste your cycles, for sure.

    As I wrote, it doesn't actually solve the bigger issue, it only solves the problem you introduce when you use pointers. Don't use pointers and the problem doesn't need solving.

    So my suggestion is to not use pointers.

    kshegunovK 1 Reply Last reply
    0
    • TomZT TomZ

      @kshegunov said in Implementing many-to-many relationships:

      Cycles pretty much irrelevant in business code

      you can waste your cycles, for sure.

      As I wrote, it doesn't actually solve the bigger issue, it only solves the problem you introduce when you use pointers. Don't use pointers and the problem doesn't need solving.

      So my suggestion is to not use pointers.

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #30

      @TomZ said in Implementing many-to-many relationships:

      Don't use pointers and the problem doesn't need solving.

      You can't not use pointers, and I imagine you know that. Neither in C, nor in C++, nor in assembly. Every heap allocation is a pointer, and even if you don't keep anything in the heap, which is dubious to begin with (with one notable exception), there are other pointers out there like C-like arrays, function pointers, lvalue references, etc.

      Read and abide by the Qt Code of Conduct

      JonBJ TomZT 2 Replies Last reply
      2
      • kshegunovK kshegunov

        @TomZ said in Implementing many-to-many relationships:

        Don't use pointers and the problem doesn't need solving.

        You can't not use pointers, and I imagine you know that. Neither in C, nor in C++, nor in assembly. Every heap allocation is a pointer, and even if you don't keep anything in the heap, which is dubious to begin with (with one notable exception), there are other pointers out there like C-like arrays, function pointers, lvalue references, etc.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #31

        @kshegunov
        Indeed. I don't understand @TomZ's post? Unless he wants to use Python/C#/Rust or whatever and claim they don't use pointers :)

        1 Reply Last reply
        0
        • kshegunovK kshegunov

          @TomZ said in Implementing many-to-many relationships:

          Don't use pointers and the problem doesn't need solving.

          You can't not use pointers, and I imagine you know that. Neither in C, nor in C++, nor in assembly. Every heap allocation is a pointer, and even if you don't keep anything in the heap, which is dubious to begin with (with one notable exception), there are other pointers out there like C-like arrays, function pointers, lvalue references, etc.

          TomZT Offline
          TomZT Offline
          TomZ
          wrote on last edited by
          #32

          @kshegunov said in Implementing many-to-many relationships:

          You can't not use pointers,

          Please look at the code sample I provided various comments back.

          It also links to some kde git repo which shows this in practice.

          Yes, you can absolutely code "without" pointers. Objects can live on stack, Qt does that in many situations by default for many objects.

          You can have a QList of QStrings. No pointers in your code at all. Same idea.

          mzimmersM 1 Reply Last reply
          0
          • TomZT TomZ

            @kshegunov said in Implementing many-to-many relationships:

            You can't not use pointers,

            Please look at the code sample I provided various comments back.

            It also links to some kde git repo which shows this in practice.

            Yes, you can absolutely code "without" pointers. Objects can live on stack, Qt does that in many situations by default for many objects.

            You can have a QList of QStrings. No pointers in your code at all. Same idea.

            mzimmersM Offline
            mzimmersM Offline
            mzimmers
            wrote on last edited by
            #33

            Hey guys - while I (truly) appreciate the points being made, what I was really looking for in my OP was opinions on sensible approaches to architecting this application. I'm more concerned with readability and maintainability than memory leaks.

            It appears that, apart from @SGaist 's original response, most people don't like the idea of intermediate tables, instead managing the relationships from within the respective objects...correct?

            kshegunovK TomZT 2 Replies Last reply
            0
            • mzimmersM mzimmers

              Hey guys - while I (truly) appreciate the points being made, what I was really looking for in my OP was opinions on sensible approaches to architecting this application. I'm more concerned with readability and maintainability than memory leaks.

              It appears that, apart from @SGaist 's original response, most people don't like the idea of intermediate tables, instead managing the relationships from within the respective objects...correct?

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #34

              @mzimmers said in Implementing many-to-many relationships:

              Hey guys - while I (truly) appreciate the points being made, what I was really looking for in my OP was opinions on sensible approaches to architecting this application. I'm more concerned with readability and maintainability than memory leaks.

              Well, they aren't exclusive and I'd rather make the argument that you shouldn't have leaks at all.

              It appears that, apart from @SGaist 's original response, most people don't like the idea of intermediate tables, instead managing the relationships from within the respective objects...correct?

              I can't speak for everyone, but I certainly don't. I'd rather architect such an application in the usual OO way, where each item is responsible for whatever it is responsible, than to have the god object that knows everything about everybody.

              @TomZ said in Implementing many-to-many relationships:

              Yes, you can absolutely code "without" pointers. Objects can live on stack, Qt does that in many situations by default for many objects.

              Yes, but sometimes, not always. Qt extensively uses owning and non-owning (weak) pointers to QObjects and that's perfectly fine. It will depend on the semantics, not the syntax (which is what a pointer is - syntax).

              You can have a QList of QStrings. No pointers in your code at all. Same idea.

              When it's a data class, and that's only because Qt already wraps the pointer inside an object to hide that detail from you and give you value semantics. This doesn't mean this is applicable to everything, or rather that you should use it for everything. Not everything is a value, so not everything can behave this way.

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • mzimmersM mzimmers

                Hey guys - while I (truly) appreciate the points being made, what I was really looking for in my OP was opinions on sensible approaches to architecting this application. I'm more concerned with readability and maintainability than memory leaks.

                It appears that, apart from @SGaist 's original response, most people don't like the idea of intermediate tables, instead managing the relationships from within the respective objects...correct?

                TomZT Offline
                TomZT Offline
                TomZ
                wrote on last edited by TomZ
                #35

                @mzimmers said in Implementing many-to-many relationships:

                opinions on sensible approaches to architecting this application.

                I would architect it the way that I suggested. A bunch of structs that get stored in maps.
                Relations between those objects happens via ints that are the 'keys' in those maps.

                Extremely easy to architect. It avoids memory overhead, avoids pointers and avoids the need to have a manager separate from your data classes as the manager IS your datastructure.

                The "make it a nice API" is what I linked to the existing example which does exactly that in:

                @TomZ said in Implementing many-to-many relationships:

                postscript; if you must, you can make all of this the private content of a 'manager' class and provide some helper classes on top to make it look all object-oriented again. (example: manager, pretty-object, implementation).

                I indeed hope we can get past the point where some don't understand it and say its a stupid idea. That's indeed not productive.

                JonBJ 1 Reply Last reply
                0
                • TomZT TomZ

                  @mzimmers said in Implementing many-to-many relationships:

                  opinions on sensible approaches to architecting this application.

                  I would architect it the way that I suggested. A bunch of structs that get stored in maps.
                  Relations between those objects happens via ints that are the 'keys' in those maps.

                  Extremely easy to architect. It avoids memory overhead, avoids pointers and avoids the need to have a manager separate from your data classes as the manager IS your datastructure.

                  The "make it a nice API" is what I linked to the existing example which does exactly that in:

                  @TomZ said in Implementing many-to-many relationships:

                  postscript; if you must, you can make all of this the private content of a 'manager' class and provide some helper classes on top to make it look all object-oriented again. (example: manager, pretty-object, implementation).

                  I indeed hope we can get past the point where some don't understand it and say its a stupid idea. That's indeed not productive.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #36

                  @TomZ said in Implementing many-to-many relationships:

                  avoids pointers

                  Umm, you mean it swaps pointers to memory for integer indexes into a map/array. No guarantee they are still valid/still have the same key as when they were created. Maybe less likely to "crash", more likely to refer to valid but incorrect information?

                  TomZT 2 Replies Last reply
                  0
                  • JonBJ JonB

                    @TomZ said in Implementing many-to-many relationships:

                    avoids pointers

                    Umm, you mean it swaps pointers to memory for integer indexes into a map/array. No guarantee they are still valid/still have the same key as when they were created. Maybe less likely to "crash", more likely to refer to valid but incorrect information?

                    TomZT Offline
                    TomZT Offline
                    TomZ
                    wrote on last edited by
                    #37

                    @JonB said in Implementing many-to-many relationships:

                    more likely to refer to valid but incorrect information?

                    Not in my experience, no.

                    Thanks for asking.

                    1 Reply Last reply
                    0
                    • JonBJ JonB

                      @TomZ said in Implementing many-to-many relationships:

                      avoids pointers

                      Umm, you mean it swaps pointers to memory for integer indexes into a map/array. No guarantee they are still valid/still have the same key as when they were created. Maybe less likely to "crash", more likely to refer to valid but incorrect information?

                      TomZT Offline
                      TomZT Offline
                      TomZ
                      wrote on last edited by
                      #38

                      @JonB said in Implementing many-to-many relationships:

                      Umm, you mean it swaps pointers to memory for integer indexes into a map/array.

                      well, yes, but no.

                      You also skip doing 'new' and 'delete'.

                      You also have all data structures in one place and thus avoid any stupid things like 'friend classes' (or large amount of accessors which have the effect of making properties public).

                      It just keeps stuff simple.

                      mzimmersM 1 Reply Last reply
                      0
                      • TomZT TomZ

                        @JonB said in Implementing many-to-many relationships:

                        Umm, you mean it swaps pointers to memory for integer indexes into a map/array.

                        well, yes, but no.

                        You also skip doing 'new' and 'delete'.

                        You also have all data structures in one place and thus avoid any stupid things like 'friend classes' (or large amount of accessors which have the effect of making properties public).

                        It just keeps stuff simple.

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #39

                        @TomZ said in Implementing many-to-many relationships:

                        You also skip doing 'new' and 'delete'.

                        Doesn't seem to me that I'd need new/delete anyway, but I do agree that it seems preferable to:

                        • create and maintain a map of Equipment objects (or structs) with a UUID as the key
                        • in the Activity object, maintain a list of Equipment UUIDs.

                        Is this what you had in mind?

                        TomZT 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          @TomZ said in Implementing many-to-many relationships:

                          You also skip doing 'new' and 'delete'.

                          Doesn't seem to me that I'd need new/delete anyway, but I do agree that it seems preferable to:

                          • create and maintain a map of Equipment objects (or structs) with a UUID as the key
                          • in the Activity object, maintain a list of Equipment UUIDs.

                          Is this what you had in mind?

                          TomZT Offline
                          TomZT Offline
                          TomZ
                          wrote on last edited by TomZ
                          #40

                          @mzimmers said in Implementing many-to-many relationships:

                          Doesn't seem to me that I'd need new/delete anyway, but I do agree that it seems preferable to:

                          create and maintain a map of Equipment objects (or structs) with a UUID as the key
                          in the Activity object, maintain a list of Equipment UUIDs.

                          Is this what you had in mind?

                          The various comments here went towards using pointers to instances of classes as the relationship. Can't use a raw pointer (safely) without 'new'.

                          If your only objects are the Equipment and the Activity, then yeah, that's pretty simple.

                          as this got confusing, here is a very quick and dirty mockup I just wrote in 5 minutes. Apologies for the roughness.

                          struct PActivity;
                          struct PEquipment;
                          
                          
                          class ManagerPrivate
                          {
                          public:
                          
                              std::map<int, PActivity> m_activities;
                              std::map<int, PEquipment> m_equipments;
                          
                             int m_lastAssignedId = 0;
                          };
                          
                          struct PActivity
                          {
                              QString name;
                          };
                          
                          struct PEquipment
                          {
                              QString name;
                              std::deque<int> activities;
                          }:
                          
                          
                          class Manager
                          {
                          public:
                              ManagerPrivate *d;
                          
                              Activity createActivity();
                          
                          };
                          
                          // ----
                          
                          
                          class Activity
                          {
                          public:
                              explicit Activity(Manager *parent, int n);
                              Activity(); // gives invalid instance.
                              bool isValid() const { return d && n; }
                          
                              QString name() const {
                                  assert(isValid());
                                  auto i = d->m_activities.find(n);
                                  assert(i != d->m_activities.end());
                                  return i->name;
                              }
                          
                              void setName(const QString &name) {
                                  assert(isValid());
                                  auto i = d->m_activities.find(n);
                                  assert(i != d->m_activities.end());
                                  i->name = name;
                              }
                          
                              int id() const { return n; }
                          
                          private:
                              ManagerPrivate *d = nullptr;
                              int n = 0;
                          };
                          
                          class Equipment
                          {
                              explicit explicit(Manager *parent, int n);
                              explicit(); // gives invalid instance.
                              bool isValid() const;
                              QString name() const;
                              void setName(const QString &name);
                          
                              void addActivity(const Activity &a) {
                                  assert(a.isValid());
                                  assert(isValid());
                                  auto i = d->m_equipments.find(n);
                                  assert(i != d->m_equipments.end());
                                  i->activities.push_back(a->id());
                              }
                          private:
                              ManagerPrivate *d = nullptr;
                              int n = 0;
                          }
                          
                          1 Reply Last reply
                          1
                          • mzimmersM mzimmers has marked this topic as solved on

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved