Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. single function to accept different parameter types
Forum Updated to NodeBB v4.3 + New Features

single function to accept different parameter types

Scheduled Pinned Locked Moved Solved C++ Gurus
23 Posts 5 Posters 3.9k Views 2 Watching
  • 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.
  • JonBJ JonB

    @mzimmers said in single function to accept different parameter types:

    @JonB an attempt at a dynamic_cast throws a std::bad_cast error,

    I have never heard of such behaviour. It is very worrying if dynamic_cast throws an error, it is supposed to be usable to detect whether an object is of a particular class at runtime, and sounds like it is what you are looking for. It is used "millions" of times in worldwide C++ code.

    Is the object/class you are testing to do with QML, or just Qt? I would not know if QML does some "funny" which could lead to this behaviour.

    You can Google dynamic_cast std::bad_cast, I didn't totally understand what they are saying, something to do with a "reference type". I only know of using it with a pointer type (hence nullptr if it fails). With a value type it would have no way of returning a "failure" result, so I guess it can only throw. Even if you have a reference type you wish to test, somehow, I imagine you can take its address: if (dynamic_cast<Bar *>(&foo_value_variable)) ....

    jsulmJ Offline
    jsulmJ Offline
    jsulm
    Lifetime Qt Champion
    wrote on last edited by
    #12

    @JonB said in single function to accept different parameter types:

    I have never heard of such behaviour

    see https://en.cppreference.com/w/cpp/language/dynamic_cast

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    JonBJ 1 Reply Last reply
    0
    • jsulmJ jsulm

      @JonB said in single function to accept different parameter types:

      I have never heard of such behaviour

      see https://en.cppreference.com/w/cpp/language/dynamic_cast

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

      @jsulm
      Yes, I know and read that. Like I (and you) said it won't happen on a pointer, and I have never used dyanmic_cast<> on anything but a pointer:

      c) Otherwise, the runtime check fails. If the dynamic_cast is used on pointers, the null pointer value of type target-type is returned. If it was used on references, the exception std::bad_cast is thrown.

      That's why I suggested how @mzimmers might test a pointer even if he starts with a value type (via &variable)..

      P.S.
      I note that qobject_cast<>() avoids this by only accepting a pointer-type, no value types!

      1 Reply Last reply
      0
      • JonBJ JonB

        @mzimmers said in single function to accept different parameter types:

        @JonB an attempt at a dynamic_cast throws a std::bad_cast error,

        I have never heard of such behaviour. It is very worrying if dynamic_cast throws an error, it is supposed to be usable to detect whether an object is of a particular class at runtime, and sounds like it is what you are looking for. It is used "millions" of times in worldwide C++ code.

        Is the object/class you are testing to do with QML, or just Qt? I would not know if QML does some "funny" which could lead to this behaviour.

        You can Google dynamic_cast std::bad_cast, I didn't totally understand what they are saying, something to do with a "reference type". I only know of using it with a pointer type (hence nullptr if it fails). With a value type it would have no way of returning a "failure" result, so I guess it can only throw. Even if you have a reference type you wish to test, somehow, I imagine you can take its address: if (dynamic_cast<Bar *>(&foo_value_variable)) ....

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #14

        @JonB said in single function to accept different parameter types:

        I have never heard of such behaviour. It is very worrying if dynamic_cast throws an error, it is supposed to be usable to detect whether an object is of a particular class at runtime, and sounds like it is what you are looking for. It is used "millions" of times in worldwide C++ code.

        I think it also throws an error when the project is compiled with -fno-rtti or /GR respectively

        and at least MSVC only gives a warning during compile time and you know what people do with warnings ^^


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        JonBJ 1 Reply Last reply
        0
        • J.HilkJ J.Hilk

          @JonB said in single function to accept different parameter types:

          I have never heard of such behaviour. It is very worrying if dynamic_cast throws an error, it is supposed to be usable to detect whether an object is of a particular class at runtime, and sounds like it is what you are looking for. It is used "millions" of times in worldwide C++ code.

          I think it also throws an error when the project is compiled with -fno-rtti or /GR respectively

          and at least MSVC only gives a warning during compile time and you know what people do with warnings ^^

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

          @J-Hilk
          I don't dispute that compilers may have options to enable it or not, e.g. disable RTTI. But the extract I quoted from cppreference above

          c) Otherwise, the runtime check fails. If the dynamic_cast is used on pointers, the null pointer value of type target-type is returned. If it was used on references, the exception std::bad_cast is thrown.

          says null pointer returned (if pointer, which is what I was discussing), I don't see it say "undefined behaviour depending on compiler". Just saying.

          In any case, I suspect @mzimmers' case is just that a pointer should be passed instead of a value.

          1 Reply Last reply
          0
          • jsulmJ jsulm

            @mzimmers said in single function to accept different parameter types:

            an attempt at a dynamic_cast throws a std::bad_cast error, and the app exits

            Can you show how you're doing this casting? If target type is a pointer you should not get std::bad_cast but a nullptr (see https://en.cppreference.com/w/cpp/language/dynamic_cast).

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

            @jsulm here's my call. I'm including it as a pic so you can see the debugger's locals window.
            Screenshot 2023-11-28 054113.png

            Vsp is a subclass of Equipment, which is a struct with Q_GADGET enabled.

            Is it possible that this error is due to the fact that equipment is being passed in as an argument from QML? I remember reading (but not fully understanding) somewhere about incompatibilities between JS and C++, and the use of emscripten to remedy it. Something about the vtables getting messed up.

            EDIT:

            I changed my function a bit:

            void EquipmentModel::sendPatchRequest(const Equipment &equipment)
            {
                const Equipment *ePtr = &equipment;
                const Vsp *vsp = dynamic_cast<const Vsp *>(ePtr);
            

            and this returned a null pointer as @JonB said it would. So, I guess the lesson is you can't use dynamic_cast to downcast references.

            Good to know, but...I'm still stuck with how to fix this issue.

            J.HilkJ 1 Reply Last reply
            0
            • mzimmersM mzimmers

              @jsulm here's my call. I'm including it as a pic so you can see the debugger's locals window.
              Screenshot 2023-11-28 054113.png

              Vsp is a subclass of Equipment, which is a struct with Q_GADGET enabled.

              Is it possible that this error is due to the fact that equipment is being passed in as an argument from QML? I remember reading (but not fully understanding) somewhere about incompatibilities between JS and C++, and the use of emscripten to remedy it. Something about the vtables getting messed up.

              EDIT:

              I changed my function a bit:

              void EquipmentModel::sendPatchRequest(const Equipment &equipment)
              {
                  const Equipment *ePtr = &equipment;
                  const Vsp *vsp = dynamic_cast<const Vsp *>(ePtr);
              

              and this returned a null pointer as @JonB said it would. So, I guess the lesson is you can't use dynamic_cast to downcast references.

              Good to know, but...I'm still stuck with how to fix this issue.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #17

              @mzimmers well, this works just fine and as expected:

              #include <iostream>
              
              // Base class
              class Base {
              public:
                  virtual ~Base() {}
              };
              
              // Derived class
              class Derived : public Base {
              public:
                  void sayHello() const {
                      std::cout << "Hello from Derived class!" << std::endl;
                  }
              };
              
              // Function that takes a const reference to a Base object
              void func(const Base& base) {
                  try {
                      const Derived& derived = dynamic_cast<const Derived&>(base);
                      derived.sayHello();
                  } catch (const std::bad_cast& e) {
                      std::cout << "dynamic_cast failed with message: " << e.what() << std::endl;
                  }
              }
              
              int main() {
                  Derived d;
                  func(d);  // This will succeed
              
                  Base b;
                  func(b);  // This will fail and catch block will execute
              }
              

              Hello from Derived class!
              dynamic_cast failed with message: std::bad_cast


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              mzimmersM 1 Reply Last reply
              0
              • J.HilkJ J.Hilk

                @mzimmers well, this works just fine and as expected:

                #include <iostream>
                
                // Base class
                class Base {
                public:
                    virtual ~Base() {}
                };
                
                // Derived class
                class Derived : public Base {
                public:
                    void sayHello() const {
                        std::cout << "Hello from Derived class!" << std::endl;
                    }
                };
                
                // Function that takes a const reference to a Base object
                void func(const Base& base) {
                    try {
                        const Derived& derived = dynamic_cast<const Derived&>(base);
                        derived.sayHello();
                    } catch (const std::bad_cast& e) {
                        std::cout << "dynamic_cast failed with message: " << e.what() << std::endl;
                    }
                }
                
                int main() {
                    Derived d;
                    func(d);  // This will succeed
                
                    Base b;
                    func(b);  // This will fail and catch block will execute
                }
                

                Hello from Derived class!
                dynamic_cast failed with message: std::bad_cast

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

                @J-Hilk yes, that works when the caller of func() is a C++ function. When it's coming from QML, I get the bad_cast error.

                So, I guess this isn't a C++ problem after all; it does have something to do with the interaction between C++ and QML. I can post something to the QML forum about it.

                M J.HilkJ 2 Replies Last reply
                0
                • mzimmersM mzimmers

                  @J-Hilk yes, that works when the caller of func() is a C++ function. When it's coming from QML, I get the bad_cast error.

                  So, I guess this isn't a C++ problem after all; it does have something to do with the interaction between C++ and QML. I can post something to the QML forum about it.

                  M Offline
                  M Offline
                  mpergand
                  wrote on last edited by mpergand
                  #19

                  @mzimmers
                  I really don't like the use of dynamic_cast here, seems unsafe.

                  I definitely do use subclassing; I just didn't show it in my snippet above.

                  I didn't think about Equipment subclass, but EquipmentModel subclass, like:

                  void VspEquipmentModel::sendPatchRequest(const Vsp &vsp)
                  

                  that way, each equipment model receives the right equipment is dealing with.
                  No more casting is needed.

                  mzimmersM 1 Reply Last reply
                  0
                  • M mpergand

                    @mzimmers
                    I really don't like the use of dynamic_cast here, seems unsafe.

                    I definitely do use subclassing; I just didn't show it in my snippet above.

                    I didn't think about Equipment subclass, but EquipmentModel subclass, like:

                    void VspEquipmentModel::sendPatchRequest(const Vsp &vsp)
                    

                    that way, each equipment model receives the right equipment is dealing with.
                    No more casting is needed.

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

                    @mpergand that would be an option, but I'm going to have about 40 subclasses of Equipment. I'd really prefer not to have to make 40 subclasses of the model just for this purpose. Plus, I'd have to instantiate the subclass 40 times, with a lot of overhead.

                    1 Reply Last reply
                    0
                    • mzimmersM mzimmers

                      @J-Hilk yes, that works when the caller of func() is a C++ function. When it's coming from QML, I get the bad_cast error.

                      So, I guess this isn't a C++ problem after all; it does have something to do with the interaction between C++ and QML. I can post something to the QML forum about it.

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #21

                      @mzimmers said in single function to accept different parameter types:

                      @J-Hilk yes, that works when the caller of func() is a C++ function. When it's coming from QML, I get the bad_cast error.

                      if its coming from qml, and you're passing the object into the call, than you're essentially already passing a pointer, I think.

                      Try

                      void EquipmentModel::sendPatchRequest(Equipment *equipment)
                      

                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      mzimmersM 1 Reply Last reply
                      0
                      • J.HilkJ J.Hilk

                        @mzimmers said in single function to accept different parameter types:

                        @J-Hilk yes, that works when the caller of func() is a C++ function. When it's coming from QML, I get the bad_cast error.

                        if its coming from qml, and you're passing the object into the call, than you're essentially already passing a pointer, I think.

                        Try

                        void EquipmentModel::sendPatchRequest(Equipment *equipment)
                        
                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by
                        #22

                        @J-Hilk said in single function to accept different parameter types:

                        Try
                        void EquipmentModel::sendPatchRequest(Equipment *equipment)

                        I did try that - I get a runtime error about passing incompatible arguments. And, I'm hardly a JS expert, but I don't think there's anything I can do on the QML side to make that signature work.

                        mzimmersM 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          @J-Hilk said in single function to accept different parameter types:

                          Try
                          void EquipmentModel::sendPatchRequest(Equipment *equipment)

                          I did try that - I get a runtime error about passing incompatible arguments. And, I'm hardly a JS expert, but I don't think there's anything I can do on the QML side to make that signature work.

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

                          One of my co-workers came up with this workaround:

                          // would entail one of these routines for each subclass,
                          // but they would all do the exact same thing.
                          void EquipmentModel::sendPatchRequest(const Vsp &equipment) {
                              sendBaseRequest(equipment);
                          }
                          
                          void EquipmentModel::sendBaseRequest(const Equipment &equipment)
                          {
                              if (m_qnrPatch == nullptr) {
                                  int i = getIndex(equipment.m_uuid);
                                  if (i == NOT_IN_LIST) {
                                      continue;
                                  }
                                  Equipment &listEntry = *(*m_list)[i];
                                  equipment.addPatchFields(listEntry, qjo, rolesToKeys); // goes to subclass function.
                          ...
                          

                          It works. Unless someone comes up with a better idea, I'll close out this topic. Thanks for all the suggestions...

                          1 Reply Last reply
                          0
                          • 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