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. Conditional operator as a statement

Conditional operator as a statement

Scheduled Pinned Locked Moved Unsolved C++ Gurus
48 Posts 9 Posters 6.2k Views 5 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

    @SimonSchroeder said in Conditional operator as a statement:

    The general rule is to never user ?:, but to use regular if/else instead.

    Hi Simon. I always read your posts with interest. To be 100% clear, you are not speaking about using ? : in general in its normal "expression-result" context are you? You have no problem with e.g. variable = b ? x() : y();, do you? Only with using it as a statement, b ? x() : y();, right? Where we are indeed all agreeing this is not a "recommended" construct.

    Reading through the C++ standard now I come across two apparently legitimate uses of ? : which are surprising to me at least, and germane to this thread.

    First, they spend time discussing what to do when either side of the : is of type void. Which I cannot see as usable in any context where the expression result is used (e.g. assignment to variable or in an if condition). This only makes sense (to me) in statement

    cond ? voidFunc() : voidFunc2();
    

    Second, they further comment on the result of the : being potentially an lvalue rather than the typical rvalue one would expect. This only makes sense (to me) in statement

    (x ? y : z) = 42;
    

    which perhaps surprisingly is apparently legitimate.

    S Offline
    S Offline
    SimonSchroeder
    wrote on last edited by
    #27

    @JonB said in Conditional operator as a statement:

    You have no problem with e.g. variable = b ? x() : y();, do you? Only with using it as a statement, b ? x() : y();, right?

    You are correct, I don't have a problem with variable assignment. (I tried to clarify this by the examples I gave.) Still, I would say the general rule is to not use them. You should only use them when you really need them. Sometimes there is no other language feature that could achieve the same thing, and then it is totally fine. Just don't be too smart about it.

    (I'm personally a heavy user of ?:. I have just accidentially found this 'beauty' in my source:

    std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
                          : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
                                        : "stats-" + std::to_string(year) + "-winter-mean.csv");
    

    MIN and MAX are enum values.)

    J.HilkJ JonBJ 2 Replies Last reply
    0
    • S SimonSchroeder

      @JonB said in Conditional operator as a statement:

      You have no problem with e.g. variable = b ? x() : y();, do you? Only with using it as a statement, b ? x() : y();, right?

      You are correct, I don't have a problem with variable assignment. (I tried to clarify this by the examples I gave.) Still, I would say the general rule is to not use them. You should only use them when you really need them. Sometimes there is no other language feature that could achieve the same thing, and then it is totally fine. Just don't be too smart about it.

      (I'm personally a heavy user of ?:. I have just accidentially found this 'beauty' in my source:

      std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
                            : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
                                          : "stats-" + std::to_string(year) + "-winter-mean.csv");
      

      MIN and MAX are enum values.)

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

      @SimonSchroeder said in Conditional operator as a statement:

      (I'm personally a heavy user of ?:. I have just accidentially found this 'beauty' in my source:

      std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
      : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
      : "stats-" + std::to_string(year) + "-winter-mean.csv");
      MIN and MAX are enum values.)

      alt text


      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.

      1 Reply Last reply
      1
      • S SimonSchroeder

        @JonB said in Conditional operator as a statement:

        You have no problem with e.g. variable = b ? x() : y();, do you? Only with using it as a statement, b ? x() : y();, right?

        You are correct, I don't have a problem with variable assignment. (I tried to clarify this by the examples I gave.) Still, I would say the general rule is to not use them. You should only use them when you really need them. Sometimes there is no other language feature that could achieve the same thing, and then it is totally fine. Just don't be too smart about it.

        (I'm personally a heavy user of ?:. I have just accidentially found this 'beauty' in my source:

        std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
                              : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
                                            : "stats-" + std::to_string(year) + "-winter-mean.csv");
        

        MIN and MAX are enum values.)

        JonBJ Online
        JonBJ Online
        JonB
        wrote on last edited by
        #29

        @SimonSchroeder

        std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
                              : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
                                            : "stats-" + std::to_string(year) + "-winter-mean.csv");
        

        I think it's fine you chose ? : here. if else would have been much longer. But just for the record I have a thing about about factoring and not repeating. I would probably have written yours as something like:

        var amount = (type == MIN) ? "min" : (type == MAX) ? "max" : "mean";
        std::ifstream in_winter("stats-" + std::to_string(year) + "-winter-" + amount + ".csv");
        

        :) To me this makes it clear that the "test" is simply for the word min/max/mean and everything else is the same. And the lines are not too long!

        J.HilkJ 1 Reply Last reply
        0
        • JonBJ JonB

          @SimonSchroeder

          std::ifstream in_winter(type == MIN ? "stats-" + std::to_string(year) + "-winter-min.csv"
                                : type == MAX ? "stats-" + std::to_string(year) + "-winter-max.csv"
                                              : "stats-" + std::to_string(year) + "-winter-mean.csv");
          

          I think it's fine you chose ? : here. if else would have been much longer. But just for the record I have a thing about about factoring and not repeating. I would probably have written yours as something like:

          var amount = (type == MIN) ? "min" : (type == MAX) ? "max" : "mean";
          std::ifstream in_winter("stats-" + std::to_string(year) + "-winter-" + amount + ".csv");
          

          :) To me this makes it clear that the "test" is simply for the word min/max/mean and everything else is the same. And the lines are not too long!

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

          @JonB I would have gone with a lambda function and a full switch case approach. We're dealing with enums after all, and it screams at me: "THIS WILL EXPAND TO MORE FILES!"


          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 I would have gone with a lambda function and a full switch case approach. We're dealing with enums after all, and it screams at me: "THIS WILL EXPAND TO MORE FILES!"

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

            @J.Hilk said in Conditional operator as a statement:

            lambda function and a full switch case approach

            Nah....!! KISS!! :)

            And for the record I wouldn't use a switch statement to return a simple value where there are only 2 explicit case and a default. Why write a multiline essay to pick between a couple of literal string values? Of course it's only IMHO, and each to their own....

            J.HilkJ 1 Reply Last reply
            0
            • JonBJ JonB

              @J.Hilk said in Conditional operator as a statement:

              lambda function and a full switch case approach

              Nah....!! KISS!! :)

              And for the record I wouldn't use a switch statement to return a simple value where there are only 2 explicit case and a default. Why write a multiline essay to pick between a couple of literal string values? Of course it's only IMHO, and each to their own....

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

              @JonB I value readability over simplicity for simplicity’s sake..


              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 I value readability over simplicity for simplicity’s sake..

                JonBJ Online
                JonBJ Online
                JonB
                wrote on last edited by JonB
                #33

                @J.Hilk I agree.
                And personally I find a couple of ? :s, in one line, as more readable than a multiple line switch statement and a lambda. Each to their own :)

                J.HilkJ 1 Reply Last reply
                0
                • JonBJ JonB

                  @J.Hilk I agree.
                  And personally I find a couple of ? :s, in one line, as more readable than a multiple line switch statement and a lambda. Each to their own :)

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

                  @JonB

                  auto winter_stats_filename = [](int year, Type type) -> std::string {
                      const char* suffix = "mean"; // Fallback
                      switch (type) {
                          case Type::MIN:  suffix = "min";  break;
                          case Type::MAX:  suffix = "max";  break;
                          case Type::MEAN: suffix = "mean"; break;
                          default:
                              assert(false && "winter_stats_filename: unexpected Type value");
                              break;
                      }
                      return "stats-" + std::to_string(year) + "-winter-" + std::string(suffix) + ".csv";
                  };
                  
                  std::ifstream in_winter(winter_stats_filename(year, type));
                  

                  I agree, sometimes I have the correct opinion and sometime the others have to wrong opinion :P


                  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

                    auto winter_stats_filename = [](int year, Type type) -> std::string {
                        const char* suffix = "mean"; // Fallback
                        switch (type) {
                            case Type::MIN:  suffix = "min";  break;
                            case Type::MAX:  suffix = "max";  break;
                            case Type::MEAN: suffix = "mean"; break;
                            default:
                                assert(false && "winter_stats_filename: unexpected Type value");
                                break;
                        }
                        return "stats-" + std::to_string(year) + "-winter-" + std::string(suffix) + ".csv";
                    };
                    
                    std::ifstream in_winter(winter_stats_filename(year, type));
                    

                    I agree, sometimes I have the correct opinion and sometime the others have to wrong opinion :P

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by JonB
                    #35

                    @J.Hilk
                    To pick whether you want min, max or mean in a string I have to read through 10 lines of your code (and check a lambda for sanity to add to it). Madness! :)

                    I can grasp

                    var amount = (type == MIN) ? "min" : (type == MAX) ? "max" : "mean";
                    

                    at a single glance.

                    (Yes, I know you have added enum-range checking in your code which adds a few lines compared to mine.)

                    J.HilkJ 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @J.Hilk
                      To pick whether you want min, max or mean in a string I have to read through 10 lines of your code (and check a lambda for sanity to add to it). Madness! :)

                      I can grasp

                      var amount = (type == MIN) ? "min" : (type == MAX) ? "max" : "mean";
                      

                      at a single glance.

                      (Yes, I know you have added enum-range checking in your code which adds a few lines compared to mine.)

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

                      @JonB I'm sorry but very time I see chained ternary operators, I get an Undertale rash.


                      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
                      1
                      • J.HilkJ J.Hilk

                        @JonB I'm sorry but very time I see chained ternary operators, I get an Undertale rash.

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by
                        #37

                        @J.Hilk Fair enough! But what is "an Undertale rash", Google talks about it in some game but that's it?

                        J.HilkJ 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @J.Hilk Fair enough! But what is "an Undertale rash", Google talks about it in some game but that's it?

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

                          @JonB Undertale is a game that’s kind of infamous among programmers for having huge, messy if-else chains in its code.
                          So when I say “Undertale rash,” I mean I get an allergic reaction to code that looks like that


                          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
                          1
                          • Chris KawaC Offline
                            Chris KawaC Offline
                            Chris Kawa
                            Lifetime Qt Champion
                            wrote on last edited by
                            #39

                            I really don't like lambdas used like this. Pack it in a function and you first have to go to the end of it to see what it's doing and then go back up to see how it is doing it. Have 2 or 3 of those in a function and the flow is completely ruined - you have to jump around and scroll multiple screens up and down to figure out what's going on.
                            I'm with @JonB on this - readability doesn't mean verbosity. Often fewer words express the intent better than paragraphs of syntax with sprinkles of what the code is actually doing.

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

                              @JonB Undertale is a game that’s kind of infamous among programmers for having huge, messy if-else chains in its code.
                              So when I say “Undertale rash,” I mean I get an allergic reaction to code that looks like that

                              JonBJ Online
                              JonBJ Online
                              JonB
                              wrote on last edited by
                              #40

                              @J.Hilk said in Conditional operator as a statement:

                              So when I say “Undertale rash,” I mean I get an allergic reaction to code that looks like that

                              Not knowing about the game or its code, I wondered if you intended "Undertail rash" and were thinking of a rash on your private back bits! :)

                              1 Reply Last reply
                              0
                              • Kent-DorfmanK Offline
                                Kent-DorfmanK Offline
                                Kent-Dorfman
                                wrote on last edited by Kent-Dorfman
                                #41

                                So which is more appropriate then? I know my choice.

                                Gas myGas(LOW_OCTANE);
                                if (engine.IsHighCompression()) { myGas = Gas(HIGH_OCTANE); }
                                

                                or

                                Gas myGas;
                                if (engine.IsHighCompression()) { 
                                    myGas = Gas(HIGH_OCTANE); 
                                } else {
                                    myGas = Gas(LOW_OCTANE);
                                }
                                

                                or

                                Gas myGas(engine.IsHighCompression() ? HIGH_OCTANE : LOW_OCTANE);
                                

                                If you meet the AI on the road, kill it.

                                JonBJ J.HilkJ 2 Replies Last reply
                                0
                                • Kent-DorfmanK Kent-Dorfman

                                  So which is more appropriate then? I know my choice.

                                  Gas myGas(LOW_OCTANE);
                                  if (engine.IsHighCompression()) { myGas = Gas(HIGH_OCTANE); }
                                  

                                  or

                                  Gas myGas;
                                  if (engine.IsHighCompression()) { 
                                      myGas = Gas(HIGH_OCTANE); 
                                  } else {
                                      myGas = Gas(LOW_OCTANE);
                                  }
                                  

                                  or

                                  Gas myGas(engine.IsHighCompression() ? HIGH_OCTANE : LOW_OCTANE);
                                  
                                  JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by
                                  #42

                                  @Kent-Dorfman
                                  The ? : one for me. If other people care I'm guessing they would be the same.

                                  1 Reply Last reply
                                  0
                                  • Kent-DorfmanK Kent-Dorfman

                                    So which is more appropriate then? I know my choice.

                                    Gas myGas(LOW_OCTANE);
                                    if (engine.IsHighCompression()) { myGas = Gas(HIGH_OCTANE); }
                                    

                                    or

                                    Gas myGas;
                                    if (engine.IsHighCompression()) { 
                                        myGas = Gas(HIGH_OCTANE); 
                                    } else {
                                        myGas = Gas(LOW_OCTANE);
                                    }
                                    

                                    or

                                    Gas myGas(engine.IsHighCompression() ? HIGH_OCTANE : LOW_OCTANE);
                                    
                                    J.HilkJ Offline
                                    J.HilkJ Offline
                                    J.Hilk
                                    Moderators
                                    wrote on last edited by
                                    #43

                                    @Kent-Dorfman

                                    3 Simple, readable, no unnecessary object construction or copy/assignment stuff. I would only question why it's not const.

                                    Wouldn't change 1. If I encountered it in a code base, but it's not my style

                                    2 urgh, there would need to be some more context in the function before I approved it in a code review :D


                                    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.

                                    1 Reply Last reply
                                    1
                                    • GrecKoG Offline
                                      GrecKoG Offline
                                      GrecKo
                                      Qt Champions 2018
                                      wrote on last edited by
                                      #44

                                      Pattern matching could help (latest proposal : P2688R5)

                                      Example usage: https://godbolt.org/z/zqenMsEch

                                      1 Reply Last reply
                                      0
                                      • Kent-DorfmanK Offline
                                        Kent-DorfmanK Offline
                                        Kent-Dorfman
                                        wrote on last edited by
                                        #45

                                        @JonB @J.Hilk
                                        Yeah, my decreasing order of preference too is 3, 1, 2...I'm guilty of (1) quite freqently during freeform though to text coding. as far as constifying everything...I'm lazy, and it stifles creativity ;^)

                                        If you meet the AI on the road, kill it.

                                        1 Reply Last reply
                                        0
                                        • S Offline
                                          S Offline
                                          SimonSchroeder
                                          wrote on last edited by
                                          #46

                                          I would expect to see 2 from C++ beginners (and maybe even intermediates). The variable declaration does not look like it is doing something. (And it behaves differently than built-in types because those stay uninitialized (up until C++26) when declared like this. Does anybody know if [[indeterminate]] would avoid calling the constructor?)

                                          I am working in a context where performance matters and I'm highly aware of unnecessary work. Option 1 would initialize once and maybe do a second assignment. Option 2 would initialize once and definitely assign afterwards. Option 3 only has a single initialization. I would go for option 3. (Even more pedantic: in option 2&3 it is not just an additional assignment, but also an additional call to the constructor (and destructor). At least use a setter in these cases.)

                                          Now, I'm really curious if as of C++26 this would be as performant as option 3:

                                          Gas myGas [[indeterminate]];
                                          if (engine.IsHighCompression()) { 
                                              myGas = Gas(HIGH_OCTANE); 
                                          } else {
                                              myGas = Gas(LOW_OCTANE);
                                          }
                                          

                                          If it is, we might rethink what the most readable and thus proper answer should be.

                                          Chris KawaC 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