ternary operator and ostreams

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Roger Leigh

    ternary operator and ostreams

    This code works (GCC 3.3.3):

    #include <iostream>
    int main()
    {
    bool a = true;
    std::cout << "True and false\n"
    << (a == true) ? 't' : 'f';
    std::cout << "\n";
    return 0;
    }

    But this code does not:

    #include <iostream>

    int main()
    {
    bool a = true;

    std::cout << "True and false\n"
    << (a == true) ? 't' : 'f'
    << "\n";

    return 0;
    }

    test.cc: In function `int main()':
    test.cc:9: error: invalid operands of types `char' and `const char[2]' to
    binary `operator<<'

    However, if I enclose the entire ternary expression in parentheses
    "((a == true) ? 't' : 'f')" then it does compile.

    What is different between these two forms? Both return a char, but
    only the latter returns a std::ostream& when used in the above
    expression.


    Many thanks,
    Roger

    --
    Roger Leigh

    Printing on GNU/Linux? http://gimp-print.sourceforge.net/
    GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
  • lilburne

    #2
    Re: ternary operator and ostreams



    Roger Leigh wrote:
    [color=blue]
    >
    > What is different between these two forms? Both return a char, but
    > only the latter returns a std::ostream& when used in the above
    > expression.
    >[/color]


    Check operator precedence:
    (a == true) ? 't' : ('f' << "\n");

    Comment

    • Jerry Coffin

      #3
      Re: ternary operator and ostreams

      In article <87r7y0f10n.fsf @wrynose.whinla tter.uklinux.ne t>, ${roger}
      @invalid.whinla tter.uklinux.ne t.invalid says...[color=blue]
      > This code works (GCC 3.3.3):[/color]

      [ snipped ]
      [color=blue]
      > But this code does not:
      >
      > #include <iostream>
      >
      > int main()
      > {
      > bool a = true;
      >
      > std::cout << "True and false\n"
      > << (a == true) ? 't' : 'f'
      > << "\n";
      >
      > return 0;
      > }[/color]

      This is a precedence problem -- the compiler is trying to treat this as:

      (a==true)? 't' : ('f' << '\n');

      I.e. trying to shift 'f' left by '\n' bits. This would actually work
      (it would typically shift 'f' left by 13 bits) except for one minor
      detail: the result of that bit-shift would be an int, and your other
      result is 't' which is a char. The compiler does insist that both
      results in a ?: be of the same type.

      When '<<' is used in its traditional role (bit-shifting) it more or less
      makes sense to be able to bit-shift an operand of ?: without extra
      parentheses. When you're using it for I/O it usually makes less sense,
      but the compiler always give the operand its original precedence and
      associativity.

      I'd also note that your '==true' is utterly vacuous and kind of stupid
      when you think about it -- 'a' starts out as a bool, and your comparison
      to true produces a bool that's always equal to a's original value.
      Since a is a bool, just use it directly:

      std::cout << (a ? 't' : 'f') << "\n";

      If you're going to compare it to true, then you probably need to compare
      the result of that comparison to true as well -- and so on indefinitely.

      Also note that iostreams already support writing bools out in text
      format, though they produce 'true' and 'false' instead of the 't' and
      'f' you've used.

      --
      Later,
      Jerry.

      The universe is a figment of its own imagination.

      Comment

      • Roger Leigh

        #4
        Re: ternary operator and ostreams

        lilburne <lilburne@godzi lla.com> writes:
        [color=blue]
        > Roger Leigh wrote:
        >[color=green]
        >> What is different between these two forms? Both return a char, but
        >> only the latter returns a std::ostream& when used in the above
        >> expression.[/color]
        >
        > Check operator precedence:
        > (a == true) ? 't' : ('f' << "\n");[/color]

        Doh! How could I have been that unobservant?


        Thanks,
        Roger

        --
        Roger Leigh

        Printing on GNU/Linux? http://gimp-print.sourceforge.net/
        GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.

        Comment

        • Roger Leigh

          #5
          Re: ternary operator and ostreams

          Jerry Coffin <jcoffin@taeus. com> writes:
          [color=blue]
          > In article <87r7y0f10n.fsf @wrynose.whinla tter.uklinux.ne t>, ${roger}
          > @invalid.whinla tter.uklinux.ne t.invalid says...[color=green]
          >> This code works (GCC 3.3.3):[/color]
          >
          > [ snipped ]
          >[color=green]
          >> But this code does not:
          >>
          >> #include <iostream>
          >>
          >> int main()
          >> {
          >> bool a = true;
          >>
          >> std::cout << "True and false\n"
          >> << (a == true) ? 't' : 'f'
          >> << "\n";
          >>
          >> return 0;
          >> }[/color][/color]
          [color=blue]
          > I'd also note that your '==true' is utterly vacuous and kind of stupid
          > when you think about it -- 'a' starts out as a bool, and your comparison
          > to true produces a bool that's always equal to a's original value.
          > Since a is a bool, just use it directly:
          >
          > std::cout << (a ? 't' : 'f') << "\n";[/color]

          That's an excellent point, thanks!
          [color=blue]
          > Also note that iostreams already support writing bools out in text
          > format, though they produce 'true' and 'false' instead of the 't' and
          > 'f' you've used.[/color]

          That's probably even better. However, I'm constructing SQL database
          queries with this, and I want to ensure the "true" and "false" will
          never be localised. From what I've seen you need to manually add this
          facility to a locale to get localised strings? I want to avoid this
          ever occuring if possible.


          --
          Roger Leigh

          Printing on GNU/Linux? http://gimp-print.sourceforge.net/
          GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.

          Comment

          • Jerry Coffin

            #6
            Re: ternary operator and ostreams

            In article <87ad4kyomd.fsf @wrynose.whinla tter.uklinux.ne t>, ${roger}
            @invalid.whinla tter.uklinux.ne t.invalid says...

            [ ... ]
            [color=blue][color=green]
            > > Also note that iostreams already support writing bools out in text
            > > format, though they produce 'true' and 'false' instead of the 't' and
            > > 'f' you've used.[/color]
            >
            > That's probably even better. However, I'm constructing SQL database
            > queries with this, and I want to ensure the "true" and "false" will
            > never be localised. From what I've seen you need to manually add this
            > facility to a locale to get localised strings? I want to avoid this
            > ever occuring if possible.[/color]

            The default global locale is the "C" locale, which will always spell
            these as "true" and "false". If you change the global locale (e.g. with
            setlocale) then you may have to explicitly imbue this stream with the
            "C" locale again to get the desired behavior. Given that it's crucial
            for it to use the "C" locale, you might want to imbue it explicitly even
            if (for now) you're never changing locales at all. IIRC, one way to do
            that should be something like this:

            /* warning: untested code */
            std::fstream SQL_stuff("file name.sql");

            std::locale def_loc("C");
            SQL_stuff.imbue (def_loc);

            This way, if you add localization code in the future, you're still
            assured that this stream will use the default locale.

            --
            Later,
            Jerry.

            The universe is a figment of its own imagination.

            Comment

            • Roger Leigh

              #7
              Re: ternary operator and ostreams

              Jerry Coffin <jcoffin@taeus. com> writes:
              [color=blue]
              > In article <87ad4kyomd.fsf @wrynose.whinla tter.uklinux.ne t>, ${roger}
              > @invalid.whinla tter.uklinux.ne t.invalid says...
              >
              > [ ... ]
              >[color=green][color=darkred]
              >> > Also note that iostreams already support writing bools out in text
              >> > format, though they produce 'true' and 'false' instead of the 't' and
              >> > 'f' you've used.[/color]
              >>
              >> That's probably even better. However, I'm constructing SQL database
              >> queries with this, and I want to ensure the "true" and "false" will
              >> never be localised. From what I've seen you need to manually add this
              >> facility to a locale to get localised strings? I want to avoid this
              >> ever occuring if possible.[/color]
              >
              > The default global locale is the "C" locale, which will always spell
              > these as "true" and "false". If you change the global locale (e.g. with
              > setlocale) then you may have to explicitly imbue this stream with the
              > "C" locale again to get the desired behavior. Given that it's crucial
              > for it to use the "C" locale, you might want to imbue it explicitly even
              > if (for now) you're never changing locales at all. IIRC, one way to do
              > that should be something like this:
              >
              > /* warning: untested code */
              > std::fstream SQL_stuff("file name.sql");
              >
              > std::locale def_loc("C");
              > SQL_stuff.imbue (def_loc);
              >
              > This way, if you add localization code in the future, you're still
              > assured that this stream will use the default locale.[/color]

              Thanks for clearing that up. I'm currently using "C", and I've
              explicitly selected "C" as the default locale, but I hope to
              internationalis e it at some point in the near future (I need to clean
              up some numeric formatting issues first). I just need to make sure
              the communcation with the database (and other programs) is
              standardised to use "C".

              I'm using std::ostringstr eam to construct the queries, so it'll be no
              big deal to explicitly imbue them with "C".


              Many thanks for your help,
              Roger

              --
              Roger Leigh

              Printing on GNU/Linux? http://gimp-print.sourceforge.net/
              GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.


              -----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
              http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
              -----== Over 100,000 Newsgroups - 19 Different Servers! =-----

              Comment

              Working...