Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Direct comparing of two QVariant variables

Direct comparing of two QVariant variables

Scheduled Pinned Locked Moved General and Desktop
66 Posts 9 Posters 48.5k 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.
  • deisikD Offline
    deisikD Offline
    deisik
    wrote on last edited by
    #1

    Is it possible to directly compare two QVariant variables for more or less without writing a chain of ifs and explicit casting of QVariant value to the stored type? I mean just base types like ints, strings, etc which allow this type of comparison

    1 Reply Last reply
    0
    • K Offline
      K Offline
      koahnig
      wrote on last edited by
      #2

      Welcome to devnet

      In the documentation you find "operator==":http://developer.qt.nokia.com/doc/qt-4.8/qvariant.html#operator-eq-eq and "operator!=":http://developer.qt.nokia.com/doc/qt-4.8/qvariant.html#operator-not-eq

      Vote the answer(s) that helped you to solve your issue(s)

      1 Reply Last reply
      0
      • deisikD Offline
        deisikD Offline
        deisik
        wrote on last edited by
        #3

        How can this help me find out which value is greater and which is less?

        1 Reply Last reply
        0
        • K Offline
          K Offline
          koahnig
          wrote on last edited by
          #4

          If you like to use QVariant for sorting or similar it has some stumblestones. The defined operators are the ones you may savely supply.

          Depending what you like to do you may write your own operator overlays. BUT it bears quite a bit of danger! Because you might have to compare non-compatible values and what return value do you want to supply?

          However, when you know the type you may do
          @
          if ( var1.toInt() > var2.toInt() )
          {
          ...
          }
          @

          Vote the answer(s) that helped you to solve your issue(s)

          1 Reply Last reply
          0
          • deisikD Offline
            deisikD Offline
            deisik
            wrote on last edited by
            #5

            This is exactly what I was all out trying to avoid. Yes, I know beforehand which types are stored in QVariant and that they are comparable this way. But writing a bunch of ifs as you suggest and as I actually do seems a bit cumbersome considering that QVariant knows at runtime which type is stored inside it (e.g. QVariant::type() function). You should see the point of frustration

            1 Reply Last reply
            0
            • K Offline
              K Offline
              koahnig
              wrote on last edited by
              #6

              You could write an overlay like:
              @
              bool operator< ( QVariant varl, QVariant varr )
              {
              if ( varl.type () == varr.type() )
              {
              return varl.to[use type] < varr.to[use type];
              }
              return [but what are you using here?];
              }
              @

              However again, if you are writing such a method you may be up to a lot of trouble. In future it might hard to find you error, when your program behaves weird.

              Vote the answer(s) that helped you to solve your issue(s)

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                You could write an operator<() for QVariant. It is not defined by default, I assume because it does not make sense for a lot of situations. What should be the result if you try to compare an integer and a QStringList, both of which can be stored in a QVariant?

                Anyway, if in your application, you deal with lots of QVariants of the same type, then it might make sense to define it anyway. The implementation may indeed need to have a lot of case statements, but you'd only need to do this once.

                1 Reply Last reply
                0
                • deisikD Offline
                  deisikD Offline
                  deisik
                  wrote on last edited by
                  #8

                  Ok, this seems a better idea. In case types mismatch the answer is obvious - assert(0) should be called

                  1 Reply Last reply
                  0
                  • deisikD Offline
                    deisikD Offline
                    deisik
                    wrote on last edited by
                    #9

                    [quote author="Andre" date="1326626635"]Anyway, if in your application, you deal with lots of QVariants of the same type, then it might make sense to define it anyway. The implementation may indeed need to have a lot of case statements, but you'd only need to do this once[/quote]

                    I have already done this and I don't like it, thus this question appearing

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #10

                      Assert is nice and all, but it will be compiled out in release mode. I think that for something like this, you might want to throw an exception. At least, you need to have defined the behaviour for the case.

                      1 Reply Last reply
                      0
                      • deisikD Offline
                        deisikD Offline
                        deisik
                        wrote on last edited by
                        #11

                        [quote author="Andre" date="1326626635"]What should be the result if you try to compare an integer and a QStringList, both of which can be stored in a QVariant?[/quote]

                        I can just as well (or as bad as you would say) compare an integer and a QStringList without the "help" of QVariant with the same result. This "type safety" seems a bit forced for a language like c/c++

                        [quote author="Andre" date="1326626947"]Assert is nice and all, but it will be compiled out in release mode. I think that for something like this, you might want to throw an exception. At least, you need to have defined the behaviour for the case. [/quote]

                        Yes, you're right, this is what I was trying to say. Actually, there is no problem if you know what you are doing

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          andre
                          wrote on last edited by
                          #12

                          [quote author="deisik" date="1326626940"][quote author="Andre" date="1326626635"]Anyway, if in your application, you deal with lots of QVariants of the same type, then it might make sense to define it anyway. The implementation may indeed need to have a lot of case statements, but you'd only need to do this once[/quote]

                          I have already done this and I don't like it, thus this question appearing

                          [/quote]

                          I guess you'd need to talk to somebody who really masters the black arts of template metaprogramming. Perhaps you could achieve this using that way, but I really don't know for sure. I think it will be very tricky, but I very well may be overlooking an obvious solution.

                          1 Reply Last reply
                          0
                          • deisikD Offline
                            deisikD Offline
                            deisik
                            wrote on last edited by
                            #13

                            [quote author="koahnig" date="1326626572"]
                            @
                            return varl.to[use type] < varr.to[use type];
                            @
                            [/quote]

                            Is it possible to make automatic conversion, so as to avoid multiple returns? Otherwise, it is just another way of writing

                            [quote author="koahnig" date="1326625090"]

                            @
                            if ( var1.toInt() > var2.toInt() )
                            {
                            ...
                            }
                            @
                            [/quote]

                            1 Reply Last reply
                            0
                            • deisikD Offline
                              deisikD Offline
                              deisik
                              wrote on last edited by
                              #14

                              [quote author="Andre" date="1326627612"]
                              I guess you'd need to talk to somebody who really masters the black arts of template metaprogramming. Perhaps you could achieve this using that way, but I really don't know for sure[/quote]

                              I think, this won't help since templates are resolved at compile-time which is surely not the case here

                              1 Reply Last reply
                              0
                              • K Offline
                                K Offline
                                koahnig
                                wrote on last edited by
                                #15

                                [quote author="deisik" date="1326627966"][quote author="koahnig" date="1326626572"]
                                @
                                return varl.to[use type] < varr.to[use type];
                                @
                                [/quote]

                                Is it possible to make automatic conversion, so as to avoid multiple returns? Otherwise, it is just another way of writing

                                [quote author="koahnig" date="1326625090"]

                                @
                                if ( var1.toInt() > var2.toInt() )
                                {
                                ...
                                }
                                @
                                [/quote]

                                [/quote]

                                At least you have to do it only once.

                                [Edit] -As Andre suggested may be if you involve the "black arts" of template meta programming. Right away nothing pops up immediately.-
                                Since we cross-posted

                                Vote the answer(s) that helped you to solve your issue(s)

                                1 Reply Last reply
                                0
                                • deisikD Offline
                                  deisikD Offline
                                  deisik
                                  wrote on last edited by
                                  #16

                                  [quote author="koahnig" date="1326629012"]
                                  At least you have to do it only once[/quote]

                                  Already done so and not satisfied. There should be a cleaner solution

                                  [quote author="koahnig" date="1326629012"]Right away nothing pops up immediately[/quote]

                                  Stuck too

                                  1 Reply Last reply
                                  0
                                  • G Offline
                                    G Offline
                                    goetz
                                    wrote on last edited by
                                    #17

                                    There cannot be a clean solution for an in principle unsolvable problem. QVariant can hold types which are plain not comparable. For int an QStringList one can imagine something fancy, but comparing a QVariantMap against a QImage is ... weird.

                                    So, you will have to constraint your comparison - this is were your home brown solution enters the game.

                                    For using a template based solution, something like this comes into mind:

                                    @
                                    template<typename T>
                                    bool qVariantLessThan(const QVariant &l, const QVariant &r)
                                    {
                                    QVariant l2 = qvariant_cast<T>(l);
                                    QVariant r2 = qvariant_cast<T>(r);

                                    if(l.type() != l2.type() || l != l2) {
                                        qFatal("QVariant lessThan: l is not of correct type!");
                                        return false;
                                    }
                                    
                                    if(r.type() != r2.type() || r != r2) {
                                        qFatal("QVariant lessThan: r is not of correct type!");
                                        return false;
                                    }
                                    
                                    return l.value<T>() < r.value<T>();
                                    

                                    }

                                    QVariant s1("x1");
                                    QVariant s2("x2");
                                    qDebug() << qVariantLessThan<QString>(s1, s2);
                                    // true

                                    QVariant i1(1);
                                    QVariant i2(-1);
                                    qDebug() << qVariantLessThan<int>(i1, i2);
                                    // false

                                    QVariant d1(1.25);
                                    QVariant d2(1.24);
                                    qDebug() << qVariantLessThan<double>(d1, d2);
                                    // false

                                    QVariant f1(1.25f);
                                    QVariant f2(1.26f);
                                    qDebug() << qVariantLessThan<float>(f1, f2);
                                    // true

                                    qDebug() << qVariantLessThan<float>(d1, f2);
                                    // error

                                    qDebug() << qVariantLessThan<float>(f1, f2);
                                    // error
                                    @

                                    I don't know whether it's possible to overload operator<() at all. Even if it was possible a syntax like

                                    @
                                    bool lessThan = x1 < <int> x2;
                                    @

                                    would be weird at best.

                                    http://www.catb.org/~esr/faqs/smart-questions.html

                                    1 Reply Last reply
                                    0
                                    • deisikD Offline
                                      deisikD Offline
                                      deisik
                                      wrote on last edited by
                                      #18

                                      [quote author="Volker" date="1326642057"]There cannot be a clean solution for an in principle unsolvable problem. QVariant can hold types which are plain not comparable. For int an QStringList one can imagine something fancy, but comparing a QVariantMap against a QImage is ... weird[/quote]

                                      If QVariant knows (and it does) about the type of the value it stores, why can't it return this value with QVariant::value() without type specification just as it returns with value<int>(), value<float>(), etc ad nauseum?

                                      [quote author="Volker" date="1326642057"]For using a template based solution, something like this comes into mind[/quote]

                                      This is not a real solution. As said before, it's better to make type casting directly in the if statement for comparison. In both cases you have to know the right type to which to convert at compile-time or to cover all possible (allowed) types. This is a real nuisance and in tight loops just a waste of cycles

                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        andre
                                        wrote on last edited by
                                        #19

                                        [quote author="deisik" date="1326646561"]If QVariant knows (and it does) about the type of the value it stores, why can't it return this value with QVariant::value() without type specification just as it returns with value<int>(), value<float>(), etc ad nauseum?[/quote]
                                        It can't do that, because C++ won't let you. You cannot overload a method by only changing its return type. The only way to do it, is the way it has been done: as a templated method. How on earth is the compiler supposed to know what the return type of QVariant::value() is?

                                        [quote author="deisik" date="1326646561"]This is not a real solution. As said before, it's better to make type casting directly in the if statement for comparison. In both cases you have to know the right type to which to convert at compile-time or to cover all possible (allowed) types. This is a real nuisance and in tight loops just a waste of cycles[/quote]

                                        I am wondering if QVariant really is the type for you. If you know you are storing a certain type, why not use that type directly then? QVariant has its uses, but in the end, it still is little more than a glorified void* after all.

                                        1 Reply Last reply
                                        0
                                        • deisikD Offline
                                          deisikD Offline
                                          deisik
                                          wrote on last edited by
                                          #20

                                          [quote author="Andre" date="1326656285"]It can't do that, because C++ won't let you. You cannot overload a method by only changing its return type. The only way to do it, is the way it has been done: as a templated method. How on earth is the compiler supposed to know what the return type of QVariant::value() is?[/quote]

                                          Why should the compiler know anything if the return type can just be a void* pointer of that very QVariant::value() without explicit type cast (or call it valueVoid() for that matter)? I don't mean overloading and again, I see no problem here - qt knows the right type, so does the programmer

                                          [quote author="Andre" date="1326656285"]I am wondering if QVariant really is the type for you. If you know you are storing a certain type, why not use that type directly then? QVariant has its uses, but in the end, it still is little more than a glorified void* after all. [/quote]

                                          I have the same thoughts but I don't like the idea of doing some very low level (read nasty) things in qt/c++. Look, in c/c++ you can easily reinterpret some portion of memory as you like on the fly and you cheerfully hope that the exact way you do this can just as easy be determined by some other bytes in memory you point to, but nope, you can't do this

                                          1 Reply Last reply
                                          0

                                          • Login

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