<string> to lowercase

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matt Wharton

    #16
    Re: &lt;string&g t; to lowercase

    "Andre Kostur" <nntpspam@kostu r.net> wrote in message
    news:Xns954985E C11153nntpspamk osturnet@207.35 .177.134...[color=blue]
    > "Matt Wharton" <noSpam@noSpam. com> wrote in news:1092853381 .442698
    > @cswreg.cos.agi lent.com:
    >[color=green]
    > > You might look at using the 'for_each' algorithm in conjunction with[/color][/color]
    the[color=blue][color=green]
    > > string's iterators and 'tolower'.[/color]
    >
    > Wouldn't you want std::transform ?
    >[/color]

    Yes, quite right; that would be better. My mistake.

    -Matt



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.m oderated. First time posters: Do this! ]

    Comment

    • Kevin W.

      #17
      Re: &lt;string&g t; to lowercase

      > using namespace std;[color=blue]
      > transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );[/color]

      A question: what does the double-colon mean in this context, and from
      which library does the tolower function come?

      --
      Kevin W :-)
      Opera/CSS/webdev blog: http://www.exclipy.com/
      Using Opera: http://www.opera.com/m2/

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.m oderated. First time posters: Do this! ]

      Comment

      • Francis Glassborow

        #18
        Re: &lt;string&g t; to lowercase

        In article <opsc2kqheljxvi i7@localhost.lo caldomain>, Kevin W.
        <contact@in.sig > writes[color=blue][color=green]
        >> using namespace std;
        >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );[/color]
        >
        >A question: what does the double-colon mean in this context, and from
        >which library does the tolower function come?[/color]

        As a using directive is in operation, ::tolower() forces the lookup to
        be only in the global namespace + any other names injected with using
        declarations. This form of disambiguation is one of the few advantages
        of using directives.

        --
        Francis Glassborow ACCU
        Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
        For project ideas and contributions: http://www.spellen.org/youcandoit/projects


        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
        [ comp.lang.c++.m oderated. First time posters: Do this! ]

        Comment

        • llewelly

          #19
          Re: &lt;string&g t; to lowercase

          kanze@gabi-soft.fr writes:
          [color=blue]
          > no.more.spam@st oneentertainmen t.com (Brian Stone) wrote in message
          > news:<acd67ea1. 0408181412.6b38 c3ca@posting.go ogle.com>...
          >[color=green]
          >> The easiest way I know is to use the transform() function from the
          >> <algorithm> library. Here's an example of how to apply this to a
          >> string to convert the case...[/color]
          >[color=green]
          >> #include <iostream>
          >> #include <string>
          >> #include <algorithm>
          >> #include <functional>
          >> #include <cctype>[/color]
          >[color=green]
          >> using namespace std;[/color]
          >[color=green]
          >> int main ( int argc, char **argv )
          >> {
          >> string A = "TeStInG!";[/color]
          >[color=green]
          >> cout << A << endl; // output: TeStInG!
          >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );
          >> cout << A << endl; // output: testing!
          >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::toupp er) );
          >> cout << A << endl; // output: TESTING!
          >> }[/color][/color]
          [snip][color=blue]
          > In fact, the only variant which compiled (and that got a warning from
          > Sun CC) is yours, with ::tolower and ::toupper. And you are playing on a
          > bug in practically every implementation of <cctype>, which exposes
          > ::tolower and ::toupper (rather than only having them available in
          > std::, as the standard requires).[/color]
          [snip]

          The 'using namespace std;' at global scope makes std::tolower
          and std::toupper be availible at global scope. (See 3.4.3.2)

          Even without the 'using namespace std', we have 17.4.3.1.3/5:

          # Each function signature from the Standard C library declared
          # with external linkage is reserved to the implementation for use
          # as a function signature with both extern "C" and extern "C++"
          # linkage, (168) or as a name of namespace scope in the global
          # namespace.


          [ See http://www.gotw.ca/resources/clcm.htm for info about ]
          [ comp.lang.c++.m oderated. First time posters: Do this! ]

          Comment

          • kanze@gabi-soft.fr

            #20
            Re: &lt;string&g t; to lowercase

            Francis Glassborow <francis@robint on.demon.co.uk> wrote in message
            news:<ZR$JqoQ2f zJBFwlU@robinto n.demon.co.uk>. ..
            [color=blue]
            > In article <opsc2kqheljxvi i7@localhost.lo caldomain>, Kevin W.
            > <contact@in.sig > writes[color=green][color=darkred]
            > >> using namespace std;
            > >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );[/color][/color][/color]
            [color=blue][color=green]
            > >A question: what does the double-colon mean in this context, and from
            > >which library does the tolower function come?[/color][/color]
            [color=blue]
            > As a using directive is in operation, ::tolower() forces the lookup to
            > be only in the global namespace + any other names injected with using
            > declarations.[/color]

            Are you sure?

            I ask because this doesn't seem to be the behavior I'm seeing with most
            compilers. If I compile exactly the original program, but with an
            #include <locale> as well (so that a couple of other tolower are
            available too), I still don't get an error about an ambiguous function;
            both g++ and Sun CC chose uniquely the tolower in <cctype> (which in
            both implementations , is actually in global namespace, instead of in
            std:: as the standard requires). Sun CC, of course, does warn that I'm
            trying to use an `extern "C"' function in a context which requires an
            `extern "C++"' one. (I think that the ::tolower that g++ picks up is
            also an `extern "C"'. If so, his code only works because of two
            successive compiler errors.)
            [color=blue]
            > This form of disambiguation is one of the few advantages of using
            > directives.[/color]

            It may be, but if so, it isn't very portable in practice, since not all
            compilers implement it correctly:-).

            And maybe I'm just dumb, but I find that the complexity here is getting
            beyond what I can master.

            --
            James Kanze GABI Software http://www.gabi-soft.fr
            Conseils en informatique orientée objet/
            Beratung in objektorientier ter Datenverarbeitu ng
            9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

            [ See http://www.gotw.ca/resources/clcm.htm for info about ]
            [ comp.lang.c++.m oderated. First time posters: Do this! ]

            Comment

            • kanze@gabi-soft.fr

              #21
              Re: &lt;string&g t; to lowercase

              "Kevin W." <contact@in.sig > wrote in message
              news:<opsc2kqhe ljxvii7@localho st.localdomain> ...
              [color=blue][color=green]
              > > using namespace std;
              > > transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );[/color][/color]
              [color=blue]
              > A question: what does the double-colon mean in this context, and from
              > which library does the tolower function come?[/color]

              It tells the compiler only to look in global namespace, not in std::.

              In the actual code in question, according to the standard, there was no
              function tolower in global namespace. In practice, however, most, if
              not all implementations are broken in this regard, and the C version of
              tolower (the one in <cctypes>) is visible in global namespace.

              Of course, he could have gotten the same effect (I think -- I'm not
              really that sure of the standard here, and of course, no two compilers
              do exactly the same thing anyway) by including <ctype.h>.

              --
              James Kanze GABI Software http://www.gabi-soft.fr
              Conseils en informatique orientée objet/
              Beratung in objektorientier ter Datenverarbeitu ng
              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

              [ See http://www.gotw.ca/resources/clcm.htm for info about ]
              [ comp.lang.c++.m oderated. First time posters: Do this! ]

              Comment

              • kanze@gabi-soft.fr

                #22
                Re: &lt;string&g t; to lowercase

                llewelly <llewelly.at@xm ission.dot.com> wrote in message
                news:<86smaepqf v.fsf@Zorthluth ik.local.bar>.. .[color=blue]
                > kanze@gabi-soft.fr writes:[/color]
                [color=blue][color=green]
                > > no.more.spam@st oneentertainmen t.com (Brian Stone) wrote in message
                > > news:<acd67ea1. 0408181412.6b38 c3ca@posting.go ogle.com>...[/color][/color]
                [color=blue][color=green][color=darkred]
                > >> The easiest way I know is to use the transform() function from the
                > >> <algorithm> library. Here's an example of how to apply this to a
                > >> string to convert the case...[/color][/color][/color]
                [color=blue][color=green][color=darkred]
                > >> #include <iostream>
                > >> #include <string>
                > >> #include <algorithm>
                > >> #include <functional>
                > >> #include <cctype>[/color][/color][/color]
                [color=blue][color=green][color=darkred]
                > >> using namespace std;[/color][/color][/color]
                [color=blue][color=green][color=darkred]
                > >> int main ( int argc, char **argv )
                > >> {
                > >> string A = "TeStInG!";[/color][/color][/color]
                [color=blue][color=green][color=darkred]
                > >> cout << A << endl; // output: TeStInG!
                > >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::tolow er) );
                > >> cout << A << endl; // output: testing!
                > >> transform ( A.begin(), A.end(), A.begin(), ptr_fun(::toupp er) );
                > >> cout << A << endl; // output: TESTING!
                > >> }[/color][/color]
                > [snip][color=green]
                > > In fact, the only variant which compiled (and that got a warning
                > > from Sun CC) is yours, with ::tolower and ::toupper. And you are
                > > playing on a bug in practically every implementation of <cctype>,
                > > which exposes ::tolower and ::toupper (rather than only having them
                > > available in std::, as the standard requires).[/color]
                > [snip][/color]
                [color=blue]
                > The 'using namespace std;' at global scope makes std::tolower
                > and std::toupper be availible at global scope. (See 3.4.3.2)[/color]

                Now if only someone would interpret the second paragraph of that section
                into something I could understand.

                There is a statement to the effect that "using-derectives are ingored in
                any namspace, including X, directly containing one or more declarations
                of m". If there is a toupper declared in :: (the standard forbids it,
                but all of the implementations I know do have one), then the
                using-directives in :: should be ignored. Which would make this code
                work. But it wouldn't work if the code, including the using directive,
                where in another namespace.

                This is all getting a bit beyond me. What I do know is that the
                compilers I have (Sun CC 5.1 and g++ 3.4.0) do NOT treat tolower and
                toupper as ambiguous here, even if I include <locale> (so that there are
                any number of toupper and tolower functions available). Whereas they do
                if I leave the :: out. So whatever the standard says...

                The whole thing has gotten me totally confused. For the moment, I'll
                just stick with my current solution :

                #include <ctype.h>

                namespace {
                struct ToUpper
                {
                char operator()( char ch ) const
                {
                return ::toupper( (unsigned char)ch ) ;
                }
                }
                }

                // ...

                transform( a.begin(), a.end(), a.begin(), ToUpper() ) ;

                It also has the advantage of not having undefined behavior when one of
                the char values happens to be negative. And it should still work even
                if an implementor eventually does come up with a conforming <cctype>.

                (Of course, in practice I never use toupper or tolower anyway, because I
                often have to deal with things like 'ß'. But I do use other functions
                in <ctype.h>, with other algorithms, and when I do, I use something like
                this.)
                [color=blue]
                > Even without the 'using namespace std', we have 17.4.3.1.3/5:[/color]
                [color=blue]
                > # Each function signature from the Standard C library declared
                > # with external linkage is reserved to the implementation for use
                > # as a function signature with both extern "C" and extern "C++"
                > # linkage, (168) or as a name of namespace scope in the global
                > # namespace.[/color]

                That's a reservation of the name; it doesn't mean that the name is
                visible. What it means is that if you define an `isupper' function at
                global scope, your program might not work.

                --
                James Kanze GABI Software http://www.gabi-soft.fr
                Conseils en informatique orientée objet/
                Beratung in objektorientier ter Datenverarbeitu ng
                9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                [ comp.lang.c++.m oderated. First time posters: Do this! ]

                Comment

                • Gabriel Dos Reis

                  #23
                  Re: &lt;string&g t; to lowercase

                  kanze@gabi-soft.fr writes:

                  [...]

                  | > The 'using namespace std;' at global scope makes std::tolower
                  | > and std::toupper be availible at global scope. (See 3.4.3.2)
                  |
                  | Now if only someone would interpret the second paragraph of that section
                  | into something I could understand.

                  I think only compiler writers care about what it means ;-p

                  | There is a statement to the effect that "using-derectives are ingored in
                  | any namspace, including X, directly containing one or more declarations
                  | of m". If there is a toupper declared in :: (the standard forbids it,
                  | but all of the implementations I know do have one), then the
                  | using-directives in :: should be ignored. Which would make this code
                  | work. But it wouldn't work if the code, including the using directive,
                  | where in another namespace.

                  The executive summary is that if you write X::m, then any actual
                  declaration of "m" in "X" hides any other declarations that would have
                  been found by searching namespaces nominated, directly or indirectly,
                  in using declarations reachable from X. If no actually declaration
                  for "m" is made in "X", then the result of the name lookup will be
                  that of applying the rule recursively to the nominated namespaces.

                  | This is all getting a bit beyond me. What I do know is that the
                  | compilers I have (Sun CC 5.1 and g++ 3.4.0) do NOT treat tolower and
                  | toupper as ambiguous here, even if I include <locale> (so that there are
                  | any number of toupper and tolower functions available). Whereas they do
                  | if I leave the :: out. So whatever the standard says...

                  because the declaration of ::toupper "hides" other declarations for
                  toupper in the used namespace std.

                  --
                  Gabriel Dos Reis
                  gdr@integrable-solutions.net

                  [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                  [ comp.lang.c++.m oderated. First time posters: Do this! ]

                  Comment

                  • kanze@gabi-soft.fr

                    #24
                    Re: &lt;string&g t; to lowercase

                    Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                    news:<m31xhwl31 n.fsf@uniton.in tegrable-solutions.net>. ..[color=blue]
                    > kanze@gabi-soft.fr writes:[/color]
                    [color=blue]
                    > [...][/color]
                    [color=blue]
                    > | > The 'using namespace std;' at global scope makes std::tolower and
                    > | > std::toupper be availible at global scope. (See 3.4.3.2)[/color]
                    [color=blue]
                    > | Now if only someone would interpret the second paragraph of that
                    > | section into something I could understand.[/color]
                    [color=blue]
                    > I think only compiler writers care about what it means ;-p[/color]

                    I think that there's a lot like that in the standard:-). Maybe one day,
                    I'll get the occasion to write a compiler, instead of just complaining
                    about them. (The current crop of compilers are pretty lousy -- they
                    always do what say, and never what I mean:-).)
                    [color=blue]
                    > | There is a statement to the effect that "using-derectives are
                    > | ingored in any namspace, including X, directly containing one or
                    > | more declarations of m". If there is a toupper declared in :: (the
                    > | standard forbids it, but all of the implementations I know do have
                    > | one), then the using-directives in :: should be ignored. Which
                    > | would make this code work. But it wouldn't work if the code,
                    > | including the using directive, where in another namespace.[/color]
                    [color=blue]
                    > The executive summary is that if you write X::m, then any actual
                    > declaration of "m" in "X" hides any other declarations that would have
                    > been found by searching namespaces nominated, directly or indirectly,
                    > in using declarations reachable from X. If no actually declaration
                    > for "m" is made in "X", then the result of the name lookup will be
                    > that of applying the rule recursively to the nominated namespaces.[/color]

                    In sum, what I had intuitively expected (and what the compilers I use
                    seem to implement). So why did the other posters say that "using
                    namespace std" meant that ::toupper would find a toupper in std::.

                    But wait a minute. If I say explicitly that the only toupper that I
                    want considered is the one in global namespace (e.g. ::toupper), and
                    there isn't one in global namespace, the compiler will look elsewhere?
                    That doesn't sound intuitively right -- I would expect an error.
                    [color=blue]
                    > | This is all getting a bit beyond me. What I do know is that the
                    > | compilers I have (Sun CC 5.1 and g++ 3.4.0) do NOT treat tolower and
                    > | toupper as ambiguous here, even if I include <locale> (so that there
                    > | are any number of toupper and tolower functions available). Whereas
                    > | they do if I leave the :: out. So whatever the standard says...[/color]
                    [color=blue]
                    > because the declaration of ::toupper "hides" other declarations for
                    > toupper in the used namespace std.[/color]

                    Except that, of course, if the libraries were conform, there wouldn't
                    have been a ::toupper in global namespace:-).

                    Anyhow, I still contend that the only "correct" solution using transform
                    involves something like:
                    boost::bind( (char (*)(char, std::locale const&))&std::t oupper,
                    _1, std::locale() )
                    For a pretty weak definition of correct, even then -- any toupper that
                    doesn't convert "Maße" to "MASSE" is irremedially broken, and won't be
                    acceptable to some of my customers.

                    --
                    James Kanze GABI Software http://www.gabi-soft.fr
                    Conseils en informatique orientée objet/
                    Beratung in objektorientier ter Datenverarbeitu ng
                    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                    [ comp.lang.c++.m oderated. First time posters: Do this! ]

                    Comment

                    • Gabriel Dos Reis

                      #25
                      Re: &lt;string&g t; to lowercase

                      kanze@gabi-soft.fr writes:

                      [...]

                      | > | There is a statement to the effect that "using-derectives are
                      | > | ingored in any namspace, including X, directly containing one or
                      | > | more declarations of m". If there is a toupper declared in :: (the
                      | > | standard forbids it, but all of the implementations I know do have
                      | > | one), then the using-directives in :: should be ignored. Which
                      | > | would make this code work. But it wouldn't work if the code,
                      | > | including the using directive, where in another namespace.
                      |
                      | > The executive summary is that if you write X::m, then any actual
                      | > declaration of "m" in "X" hides any other declarations that would have
                      | > been found by searching namespaces nominated, directly or indirectly,
                      | > in using declarations reachable from X. If no actually declaration
                      | > for "m" is made in "X", then the result of the name lookup will be
                      | > that of applying the rule recursively to the nominated namespaces.
                      |
                      | In sum, what I had intuitively expected (and what the compilers I use
                      | seem to implement). So why did the other posters say that "using
                      | namespace std" meant that ::toupper would find a toupper in std::.

                      I cannot speak for them and I hope they will clarify hat they meant.
                      And to tell the truth, I've lost most of those postings.

                      | But wait a minute. If I say explicitly that the only toupper that I
                      | want considered is the one in global namespace (e.g. ::toupper), and
                      | there isn't one in global namespace, the compiler will look elsewhere?

                      Yes. This is called in TC++PL3 "namespace composition" -- you trick
                      people into thinking that the "m" they're referring to in X::m comes
                      from your "X", whereas you may have just "stolen" it through
                      using-directives. E.g.

                      namespace N {
                      int m;
                      };

                      namespace X {
                      using namespace N; // compose X with N
                      }

                      int main()
                      {
                      return X::m; // finds N::m;
                      }

                      | That doesn't sound intuitively right -- I would expect an error.

                      I guess, it depends on how you look at the "::".
                      A view is that it is a scope resolution operator, i.e. it
                      disambiguates when there is a scope problem -- either there is no
                      visible declaration or there are too many visible declarations from
                      different scopes.

                      | > | This is all getting a bit beyond me. What I do know is that the
                      | > | compilers I have (Sun CC 5.1 and g++ 3.4.0) do NOT treat tolower and
                      | > | toupper as ambiguous here, even if I include <locale> (so that there
                      | > | are any number of toupper and tolower functions available). Whereas
                      | > | they do if I leave the :: out. So whatever the standard says...
                      |
                      | > because the declaration of ::toupper "hides" other declarations for
                      | > toupper in the used namespace std.
                      |
                      | Except that, of course, if the libraries were conform, there wouldn't
                      | have been a ::toupper in global namespace:-).

                      Yes, but you (James) won't quibble me on that; right? :-)

                      | Anyhow, I still contend that the only "correct" solution using transform
                      | involves something like:
                      | boost::bind( (char (*)(char, std::locale const&))&std::t oupper,
                      | _1, std::locale() )

                      I really do dislike the cast notation in front of std::toupper. It is
                      not a cast, it is an abuse of notation (manual overload resolution).
                      People should not be tricked into thinking that someone is doing a
                      weird cast from std::toupper; let's sequester cast notations to cast.

                      --
                      Gabriel Dos Reis
                      gdr@integrable-solutions.net

                      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                      [ comp.lang.c++.m oderated. First time posters: Do this! ]

                      Comment

                      • kanze@gabi-soft.fr

                        #26
                        Re: &lt;string&g t; to lowercase

                        Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                        news:<m34qmpntk x.fsf@uniton.in tegrable-solutions.net>. ..[color=blue]
                        > kanze@gabi-soft.fr writes:[/color]
                        [color=blue]
                        > [...][/color]
                        [color=blue]
                        > | > | There is a statement to the effect that "using-derectives are
                        > | > | ingored in any namspace, including X, directly containing one or
                        > | > | more declarations of m". If there is a toupper declared in ::
                        > | > | (the standard forbids it, but all of the implementations I know
                        > | > | do have one), then the using-directives in :: should be ignored.
                        > | > | Which would make this code work. But it wouldn't work if the
                        > | > | code, including the using directive, where in another namespace.[/color]
                        [color=blue]
                        > | > The executive summary is that if you write X::m, then any actual
                        > | > declaration of "m" in "X" hides any other declarations that would
                        > | > have been found by searching namespaces nominated, directly or
                        > | > indirectly, in using declarations reachable from X. If no actually
                        > | > declaration for "m" is made in "X", then the result of the name
                        > | > lookup will be that of applying the rule recursively to the
                        > | > nominated namespaces.[/color]
                        [color=blue]
                        > | In sum, what I had intuitively expected (and what the compilers I
                        > | use seem to implement). So why did the other posters say that
                        > | "using namespace std" meant that ::toupper would find a toupper in
                        > | std::.[/color]
                        [color=blue]
                        > I cannot speak for them and I hope they will clarify hat they meant.
                        > And to tell the truth, I've lost most of those postings.[/color]

                        I may have misunderstood what they were trying to say, but I got the
                        impression from them that what they were saying was that the =AB using
                        namespace std =BB was why the compiler was finding a toupper in std
                        namespace.
                        [color=blue]
                        > | But wait a minute. If I say explicitly that the only toupper that I
                        > | want considered is the one in global namespace (e.g. ::toupper), and
                        > | there isn't one in global namespace, the compiler will look
                        > | elsewhere?[/color]
                        [color=blue]
                        > Yes. This is called in TC++PL3 "namespace composition" -- you trick
                        > people into thinking that the "m" they're referring to in X::m comes
                        > from your "X", whereas you may have just "stolen" it through
                        > using-directives. E.g.[/color]
                        [color=blue]
                        > namespace N {
                        > int m;
                        > };[/color]
                        [color=blue]
                        > namespace X {
                        > using namespace N; // compose X with N
                        > }[/color]
                        [color=blue]
                        > int main()
                        > {
                        > return X::m; // finds N::m;
                        > }[/color]
                        [color=blue]
                        > | That doesn't sound intuitively right -- I would expect an error.[/color]
                        [color=blue]
                        > I guess, it depends on how you look at the "::".[/color]

                        Yes. It occured to me shortly after posting that this is sort of the
                        way the :: works within a class hierarchy. It will look deeper than the
                        classname given, but only if it doesn't find the name in the first
                        class.

                        The analogy is far from exact, but it is enough to make me suspicious of
                        my "intuitivel y". The situation has enough variety that there is no
                        intuitiveity.
                        [color=blue]
                        > A view is that it is a scope resolution operator, i.e. it
                        > disambiguates when there is a scope problem -- either there is no
                        > visible declaration or there are too many visible declarations from
                        > different scopes.[/color]
                        [color=blue]
                        > | > | This is all getting a bit beyond me. What I do know is that the
                        > | > | compilers I have (Sun CC 5.1 and g++ 3.4.0) do NOT treat tolower
                        > | > | and toupper as ambiguous here, even if I include <locale> (so
                        > | > | that there are any number of toupper and tolower functions
                        > | > | available). Whereas they do if I leave the :: out. So whatever
                        > | > | the standard says...[/color]
                        [color=blue]
                        > | > because the declaration of ::toupper "hides" other declarations
                        > | > for toupper in the used namespace std.[/color]
                        [color=blue]
                        > | Except that, of course, if the libraries were conform, there
                        > | wouldn't have been a ::toupper in global namespace:-).[/color]
                        [color=blue]
                        > Yes, but you (James) won't quibble me on that; right? :-)[/color]

                        Well, I don't think that it's your fault, even if you actively work on
                        one of the libraries:-).

                        Realisticly, I wonder if the standard doesn't ask too much here. Maybe
                        it should make it unspecified whether <cctype> introduces the names into
                        global scope or not. Theoretically, I find what the standard requires
                        much better, but that doesn't do me any good if all of the implementors
                        ignore the requirement.
                        [color=blue]
                        > | Anyhow, I still contend that the only "correct" solution using
                        > | transform involves something like:
                        > | boost::bind( (char (*)(char, std::locale const&))&std::t oupper,
                        > | _1, std::locale() )[/color]
                        [color=blue]
                        > I really do dislike the cast notation in front of std::toupper. It is
                        > not a cast, it is an abuse of notation (manual overload resolution).
                        > People should not be tricked into thinking that someone is doing a
                        > weird cast from std::toupper; let's sequester cast notations to cast.[/color]

                        I said correct, and I even put correct in quotes; I certainly didn't say
                        that it was elegant, nor that I liked it:-). For once, in fact, I agree
                        with you 100%.
                        [color=blue]
                        >From a pratical point of view: it's what the standard says, and most, if[/color]
                        not all, implementations seem to be conformant on this particular point.[color=blue]
                        >From an even more pratical point of view: it's overly complex, totally[/color]
                        illegible, and so not really maintainable. In production code, I'd
                        always write a custom function which used the standard function, so that
                        overload resolution would handle the issue automatically.

                        --
                        James Kanze GABI Software http://www.gabi-soft.fr
                        Conseils en informatique orient=E9e objet/
                        Beratung in objektorientier ter Datenverarbeitu ng
                        9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34

                        [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                        [ comp.lang.c++.m oderated. First time posters: Do this! ]

                        Comment

                        • llewelly

                          #27
                          Re: &lt;string&g t; to lowercase

                          kanze@gabi-soft.fr writes:
                          [color=blue]
                          > Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                          > news:<m34qmpntk x.fsf@uniton.in tegrable-solutions.net>. ..[color=green]
                          >> kanze@gabi-soft.fr writes:[/color]
                          >[color=green]
                          >> [...][/color]
                          >[color=green]
                          >> | > | There is a statement to the effect that "using-derectives are
                          >> | > | ingored in any namspace, including X, directly containing one or
                          >> | > | more declarations of m". If there is a toupper declared in ::
                          >> | > | (the standard forbids it, but all of the implementations I know
                          >> | > | do have one), then the using-directives in :: should be ignored.
                          >> | > | Which would make this code work. But it wouldn't work if the
                          >> | > | code, including the using directive, where in another namespace.[/color]
                          >[color=green]
                          >> | > The executive summary is that if you write X::m, then any actual
                          >> | > declaration of "m" in "X" hides any other declarations that would
                          >> | > have been found by searching namespaces nominated, directly or
                          >> | > indirectly, in using declarations reachable from X. If no actually
                          >> | > declaration for "m" is made in "X", then the result of the name
                          >> | > lookup will be that of applying the rule recursively to the
                          >> | > nominated namespaces.[/color]
                          >[color=green]
                          >> | In sum, what I had intuitively expected (and what the compilers I
                          >> | use seem to implement). So why did the other posters say that
                          >> | "using namespace std" meant that ::toupper would find a toupper in
                          >> | std::.[/color]
                          >[color=green]
                          >> I cannot speak for them and I hope they will clarify hat they meant.
                          >> And to tell the truth, I've lost most of those postings.[/color]
                          >
                          > I may have misunderstood what they were trying to say, but I got the
                          > impression from them that what they were saying was that the =AB using
                          > namespace std =BB was why the compiler was finding a toupper in std
                          > namespace.[/color]

                          That's my understanding. I get it from 3.4.3/4 :

                          # A name prefixed by the unary scope operator :: (5.1) is looked
                          # up in global scope, in the translation unit where it is
                          # used. The name shall be declared in global namespace scope or
                          # shall be a name whose declaration is visible in global scope
                          # because of a using-directive (3.4.3.2). The use of :: allows a
                          # global name to be referred to even if its identifier has been
                          # hidden (3.3.7).

                          Note that I think 17.4.3.1.3/4 (see below) allows 'toupper' to be
                          found in the global namespace even without the 'using namespace
                          std'; AFAICT the 'using namespace std' servers only to require
                          that the name found have the semantics you expect for 'toupper',
                          as opposed to implementation-defined semantics.

                          [snip][color=blue]
                          > Realisticly, I wonder if the standard doesn't ask too much here. Maybe
                          > it should make it unspecified whether <cctype> introduces the names into
                          > global scope or not.[/color]
                          [snip]

                          I think the standard already goes farther than that, see 17.4.3.1.3/4:

                          # Each name from the Standard C library declared with external
                          # linkage is reserved to the implementation for use as a name with
                          # extern "C" linkage, both in namespace std and in the global
                          # namespace.

                          There has been some dispute here and on comp.std.c++ about what this
                          means, but my interpretation (which I would rather be wrong) is
                          that if a name such as 'toupper' is *not* brought into the global
                          namespace by a sequence such as:

                          #include<cstdde f>
                          using namespace std;

                          '::toupper' has implementation-defined semantics.

                          Someday, I am going to to make time to test snippets such as:

                          //note - no headers #included.
                          extern "C" double qsort(double,do uble,double,dou ble);

                          int main()
                          {
                          double d= qsort(1.0,1.0,1 .0,1.0);
                          return (int)d;
                          }

                          on several different implementations . (On g++ 3.4 on freebsd, it
                          compiles with no errors or warnings, and dumps core at runtime. )
                          [color=blue]
                          > Theoretically, I find what the standard requires
                          > much better,[/color]

                          I think you're mistaken about what it requires, though I wish you
                          were right.
                          [color=blue]
                          > but that doesn't do me any good if all of the implementors
                          > ignore the requirement.[/color]

                          Agreed. I do wonder if #including the C++ <cxxx> headers is actually
                          more dangerous than #including the older equivalent inherted from
                          C89 .
                          [color=blue]
                          >[color=green]
                          >> | Anyhow, I still contend that the only "correct" solution using
                          >> | transform involves something like:
                          >> | boost::bind( (char (*)(char, std::locale const&))&std::t oupper,
                          >> | _1, std::locale() )[/color]
                          >[color=green]
                          >> I really do dislike the cast notation in front of std::toupper. It is
                          >> not a cast, it is an abuse of notation (manual overload resolution).
                          >> People should not be tricked into thinking that someone is doing a
                          >> weird cast from std::toupper; let's sequester cast notations to cast.[/color]
                          >
                          > I said correct, and I even put correct in quotes; I certainly didn't say
                          > that it was elegant, nor that I liked it:-). For once, in fact, I agree
                          > with you 100%.
                          >[color=green]
                          >>From a pratical point of view: it's what the standard says, and most, if[/color]
                          > not all, implementations seem to be conformant on this particular point.[color=green]
                          >>From an even more pratical point of view: it's overly complex, totally[/color]
                          > illegible, and so not really maintainable.[/color]

                          In some cases (though not the above) I find it cleaner to specify the
                          template arguments to the function template explicitly.
                          [color=blue]
                          > In production code, I'd
                          > always write a custom function which used the standard function, so that
                          > overload resolution would handle the issue automatically.[/color]
                          [snip]

                          Agreed.

                          [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                          [ comp.lang.c++.m oderated. First time posters: Do this! ]

                          Comment

                          • kanze@gabi-soft.fr

                            #28
                            Re: &lt;string&g t; to lowercase

                            llewelly <llewelly.at@xm ission.dot.com> wrote in message
                            news:<86oekqmxi b.fsf@Zorthluth ik.local.bar>.. .[color=blue]
                            > kanze@gabi-soft.fr writes:[/color]
                            [color=blue][color=green]
                            > > Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                            > > news:<m34qmpntk x.fsf@uniton.in tegrable-solutions.net>. ..[color=darkred]
                            > >> kanze@gabi-soft.fr writes:[/color][/color][/color]
                            [color=blue][color=green][color=darkred]
                            > >> [...][/color][/color][/color]
                            [color=blue][color=green][color=darkred]
                            > >> | > | There is a statement to the effect that "using-derectives
                            > >> | > | are ingored in any namspace, including X, directly
                            > >> | > | containing one or more declarations of m". If there is a
                            > >> | > | toupper declared in :: (the standard forbids it, but all of
                            > >> | > | the implementations I know do have one), then the
                            > >> | > | using-directives in :: should be ignored. Which would make
                            > >> | > | this code work. But it wouldn't work if the code, including
                            > >> | > | the using directive, where in another namespace.[/color][/color][/color]
                            [color=blue][color=green][color=darkred]
                            > >> | > The executive summary is that if you write X::m, then any
                            > >> | > actual declaration of "m" in "X" hides any other declarations
                            > >> | > that would have been found by searching namespaces nominated,
                            > >> | > directly or indirectly, in using declarations reachable from
                            > >> | > X. If no actually declaration for "m" is made in "X", then the
                            > >> | > result of the name lookup will be that of applying the rule
                            > >> | > recursively to the nominated namespaces.[/color][/color][/color]
                            [color=blue][color=green][color=darkred]
                            > >> | In sum, what I had intuitively expected (and what the compilers
                            > >> | I use seem to implement). So why did the other posters say that
                            > >> | "using namespace std" meant that ::toupper would find a toupper
                            > >> | in std::.[/color][/color][/color]
                            [color=blue][color=green][color=darkred]
                            > >> I cannot speak for them and I hope they will clarify hat they
                            > >> meant. And to tell the truth, I've lost most of those postings.[/color][/color][/color]
                            [color=blue][color=green]
                            > > I may have misunderstood what they were trying to say, but I got
                            > > the impression from them that what they were saying was that the
                            > > =AB using namespace std =BB was why the compiler was finding a
                            > > toupper in std namespace.[/color][/color]
                            [color=blue]
                            > That's my understanding. I get it from 3.4.3/4 :[/color]
                            [color=blue]
                            > # A name prefixed by the unary scope operator :: (5.1) is looked
                            > # up in global scope, in the translation unit where it is
                            > # used. The name shall be declared in global namespace scope or
                            > # shall be a name whose declaration is visible in global scope
                            > # because of a using-directive (3.4.3.2). The use of :: allows a
                            > # global name to be referred to even if its identifier has been
                            > # hidden (3.3.7).[/color]

                            There are two things involved here. First, although the standard
                            doesn't allow it, there is a toupper in global namespace. Second, there
                            are a number of toupper in std:: (since in the implementation I use,
                            <iostream> does indirectly pull in <locale>). What I don't understand
                            is this: having done "using namespace std:",

                            - if I write ::toupper, and the toupper in global namespace isn't
                            available, do I find the toupper in std::, and

                            - if the above is true, and I do have a toupper in global namespace,
                            why isn't the function call ambiguous.

                            (I think that to really understand this, I'm going to have to find time
                            to write up some simple examples of my own. It's difficult following
                            toupper, because you are never 100% sure what the library may have done
                            with it.)
                            [color=blue]
                            > Note that I think 17.4.3.1.3/4 (see below) allows 'toupper' to be
                            > found in the global namespace even without the 'using namespace
                            > std'; AFAICT the 'using namespace std' servers only to require
                            > that the name found have the semantics you expect for 'toupper',
                            > as opposed to implementation-defined semantics.[/color]

                            I'm not sure. It certainly means that I cannot define a toupper of my
                            own in global namespace.

                            I think the intent is just a pratical one (for compiler implementers).
                            Regardless of the namespace in which I declare or define an ``extern
                            "C"'' function, the name must appear to the linker as if the function
                            were defined in the global namespace, since C can't do it any
                            differently. If the name isn't reserved to the implementation, I could
                            legally define a function of this name myself, and the linker would take
                            it instead of the one from the C library. That doesn't mean that my
                            code can see the name outside of std::.

                            But there may be other "special features" of ``extern "C"'' that I'm not
                            familiar with, which do make if visible.
                            [color=blue]
                            > [snip][color=green]
                            > > Realisticly, I wonder if the standard doesn't ask too much here.
                            > > Maybe it should make it unspecified whether <cctype> introduces the
                            > > names into global scope or not.[/color]
                            > [snip]
                            >
                            > I think the standard already goes farther than that, see 17.4.3.1.3/4:[/color]
                            [color=blue]
                            > # Each name from the Standard C library declared with external
                            > # linkage is reserved to the implementation for use as a name
                            > # with extern "C" linkage, both in namespace std and in the
                            > # global namespace.[/color]

                            The name is reserved to the implementation. That doesn't mean that I
                            can see it. Or does it?

                            I think a clarification is in order.
                            [color=blue]
                            > There has been some dispute here and on comp.std.c++ about what this
                            > means, but my interpretation (which I would rather be wrong) is
                            > that if a name such as 'toupper' is *not* brought into the global
                            > namespace by a sequence such as:[/color]
                            [color=blue]
                            > #include<cstdde f>
                            > using namespace std;[/color]
                            [color=blue]
                            > '::toupper' has implementation-defined semantics.[/color]

                            What interests me is what happens without the "using namespace std;".
                            Is the compiler still allowed to find toupper?
                            [color=blue]
                            > Someday, I am going to to make time to test snippets such as:[/color]
                            [color=blue]
                            > //note - no headers #included.
                            > extern "C" double qsort(double,do uble,double,dou ble);[/color]
                            [color=blue]
                            > int main()
                            > {
                            > double d= qsort(1.0,1.0,1 .0,1.0);
                            > return (int)d;
                            > }[/color]
                            [color=blue]
                            > on several different implementations . (On g++ 3.4 on freebsd, it
                            > compiles with no errors or warnings, and dumps core at runtime. )[/color]

                            As far as I can see, you've violated §17.4.3.1.3/5, so your code has
                            undefined behavior. (Or does this paragraph only apply if you include
                            at least one standard header?)
                            [color=blue][color=green]
                            > > Theoretically, I find what the standard requires much better,[/color][/color]
                            [color=blue]
                            > I think you're mistaken about what it requires, though I wish you
                            > were right.[/color]

                            I think it is open to interpretation.

                            Personally, for the moment, I stick with the good old <ctype.h> -- at
                            least I know what I'm getting:-). Sort of, because of course,
                            <ctype.h> can, in fact, I think it should, also expose the names in
                            std::. In practice, I don't think it does, most of the time.
                            [color=blue][color=green]
                            > > but that doesn't do me any good if all of the implementors ignore
                            > > the requirement.[/color][/color]
                            [color=blue]
                            > Agreed. I do wonder if #including the C++ <cxxx> headers is actually
                            > more dangerous than #including the older equivalent inherted from
                            > C89 .[/color]

                            That's been my fear. I don't know whether it is really justified by the
                            standard, but it does seem that what actual implementations do is less
                            clear than in the case of <ctype.h>. (Of course, one of the actual
                            implementations I still have to deal with is g++ 2.95.2. Which
                            complicates the issue because of its particular handling of std::.)

                            --
                            James Kanze GABI Software http://www.gabi-soft.fr
                            Conseils en informatique orientée objet/
                            Beratung in objektorientier ter Datenverarbeitu ng
                            9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                            [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                            [ comp.lang.c++.m oderated. First time posters: Do this! ]

                            Comment

                            • Gabriel Dos Reis

                              #29
                              Re: &lt;string&g t; to lowercase

                              kanze@gabi-soft.fr writes:

                              | llewelly <llewelly.at@xm ission.dot.com> wrote in message
                              | news:<86oekqmxi b.fsf@Zorthluth ik.local.bar>.. .
                              | > kanze@gabi-soft.fr writes:
                              |
                              | > > Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                              | > > news:<m34qmpntk x.fsf@uniton.in tegrable-solutions.net>. ..
                              | > >> kanze@gabi-soft.fr writes:
                              |
                              | > >> [...]
                              |
                              | > >> | > | There is a statement to the effect that "using-derectives
                              | > >> | > | are ingored in any namspace, including X, directly
                              | > >> | > | containing one or more declarations of m". If there is a
                              | > >> | > | toupper declared in :: (the standard forbids it, but all of
                              | > >> | > | the implementations I know do have one), then the
                              | > >> | > | using-directives in :: should be ignored. Which would make
                              | > >> | > | this code work. But it wouldn't work if the code, including
                              | > >> | > | the using directive, where in another namespace.
                              |
                              | > >> | > The executive summary is that if you write X::m, then any
                              | > >> | > actual declaration of "m" in "X" hides any other declarations
                              | > >> | > that would have been found by searching namespaces nominated,
                              | > >> | > directly or indirectly, in using declarations reachable from
                              | > >> | > X. If no actually declaration for "m" is made in "X", then the
                              | > >> | > result of the name lookup will be that of applying the rule
                              | > >> | > recursively to the nominated namespaces.
                              |
                              | > >> | In sum, what I had intuitively expected (and what the compilers
                              | > >> | I use seem to implement). So why did the other posters say that
                              | > >> | "using namespace std" meant that ::toupper would find a toupper
                              | > >> | in std::.
                              |
                              | > >> I cannot speak for them and I hope they will clarify hat they
                              | > >> meant. And to tell the truth, I've lost most of those postings.
                              |
                              | > > I may have misunderstood what they were trying to say, but I got
                              | > > the impression from them that what they were saying was that the
                              | > > =AB using namespace std =BB was why the compiler was finding a
                              | > > toupper in std namespace.
                              |
                              | > That's my understanding. I get it from 3.4.3/4 :
                              |
                              | > # A name prefixed by the unary scope operator :: (5.1) is looked
                              | > # up in global scope, in the translation unit where it is
                              | > # used. The name shall be declared in global namespace scope or
                              | > # shall be a name whose declaration is visible in global scope
                              | > # because of a using-directive (3.4.3.2). The use of :: allows a
                              | > # global name to be referred to even if its identifier has been
                              | > # hidden (3.3.7).
                              |
                              | There are two things involved here. First, although the standard
                              | doesn't allow it, there is a toupper in global namespace. Second, there
                              | are a number of toupper in std:: (since in the implementation I use,
                              | <iostream> does indirectly pull in <locale>). What I don't understand
                              | is this: having done "using namespace std:",
                              |
                              | - if I write ::toupper, and the toupper in global namespace isn't
                              | available, do I find the toupper in std::, and

                              Yes, I already explained why.

                              | - if the above is true, and I do have a toupper in global namespace,
                              | why isn't the function call ambiguous.

                              Because the declaration at the global scope "hides" other declarations
                              available through used namespaces. See my previous explanation.

                              | (I think that to really understand this, I'm going to have to find time
                              | to write up some simple examples of my own. It's difficult following
                              | toupper, because you are never 100% sure what the library may have done
                              | with it.)

                              Probably.

                              --
                              Gabriel Dos Reis
                              gdr@integrable-solutions.net

                              [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                              [ comp.lang.c++.m oderated. First time posters: Do this! ]

                              Comment

                              • Gabriel Dos Reis

                                #30
                                Re: &lt;string&g t; to lowercase

                                llewelly <llewelly.at@xm ission.dot.com> writes:

                                | kanze@gabi-soft.fr writes:
                                |
                                | > Gabriel Dos Reis <gdr@integrab le-solutions.net> wrote in message
                                | > news:<m34qmpntk x.fsf@uniton.in tegrable-solutions.net>. ..
                                | >> kanze@gabi-soft.fr writes:
                                | >
                                | >> [...]
                                | >
                                | >> | > | There is a statement to the effect that "using-derectives are
                                | >> | > | ingored in any namspace, including X, directly containing one or
                                | >> | > | more declarations of m". If there is a toupper declared in ::
                                | >> | > | (the standard forbids it, but all of the implementations I know
                                | >> | > | do have one), then the using-directives in :: should be ignored.
                                | >> | > | Which would make this code work. But it wouldn't work if the
                                | >> | > | code, including the using directive, where in another namespace.
                                | >
                                | >> | > The executive summary is that if you write X::m, then any actual
                                | >> | > declaration of "m" in "X" hides any other declarations that would
                                | >> | > have been found by searching namespaces nominated, directly or
                                | >> | > indirectly, in using declarations reachable from X. If no actually
                                | >> | > declaration for "m" is made in "X", then the result of the name
                                | >> | > lookup will be that of applying the rule recursively to the
                                | >> | > nominated namespaces.
                                | >
                                | >> | In sum, what I had intuitively expected (and what the compilers I
                                | >> | use seem to implement). So why did the other posters say that
                                | >> | "using namespace std" meant that ::toupper would find a toupper in
                                | >> | std::.
                                | >
                                | >> I cannot speak for them and I hope they will clarify hat they meant.
                                | >> And to tell the truth, I've lost most of those postings.
                                | >
                                | > I may have misunderstood what they were trying to say, but I got the
                                | > impression from them that what they were saying was that the =AB using
                                | > namespace std =BB was why the compiler was finding a toupper in std
                                | > namespace.
                                |
                                | That's my understanding. I get it from 3.4.3/4 :
                                |
                                | # A name prefixed by the unary scope operator :: (5.1) is looked
                                | # up in global scope, in the translation unit where it is
                                | # used. The name shall be declared in global namespace scope or
                                | # shall be a name whose declaration is visible in global scope
                                | # because of a using-directive (3.4.3.2). The use of :: allows a
                                | # global name to be referred to even if its identifier has been
                                | # hidden (3.3.7).


                                What this says is that with ::toupper, you find those in the
                                global namespace *if* there are corresponding declarations there;
                                *otherwise*, you find those available through searching of used
                                namespaces (directly or indirectly). In particular, you do NOT find
                                both categoriss.

                                | Note that I think 17.4.3.1.3/4 (see below) allows 'toupper' to be
                                | found in the global namespace even without the 'using namespace
                                | std';

                                No, it does not. What that paragraph means is that a user does cannot
                                define them at global scope, or declare them with C language linkage.

                                | AFAICT the 'using namespace std' servers only to require
                                | that the name found have the semantics you expect for 'toupper',
                                | as opposed to implementation-defined semantics.
                                |
                                | [snip]
                                | > Realisticly, I wonder if the standard doesn't ask too much here. Maybe
                                | > it should make it unspecified whether <cctype> introduces the names into
                                | > global scope or not.
                                | [snip]
                                |
                                | I think the standard already goes farther than that, see 17.4.3.1.3/4:
                                |
                                | # Each name from the Standard C library declared with external
                                | # linkage is reserved to the implementation for use as a name with
                                | # extern "C" linkage, both in namespace std and in the global
                                | # namespace.
                                |
                                | There has been some dispute here and on comp.std.c++ about what this
                                | means, but my interpretation (which I would rather be wrong) is
                                | that if a name such as 'toupper' is *not* brought into the global
                                | namespace by a sequence such as:
                                |
                                | #include<cstdde f>
                                | using namespace std;
                                |
                                | '::toupper' has implementation-defined semantics.

                                I don't see how you derive tht. Certainly <cstddef> is not described
                                to define namespace in the global namespace.

                                | Someday, I am going to to make time to test snippets such as:
                                |
                                | //note - no headers #included.
                                | extern "C" double qsort(double,do uble,double,dou ble);

                                Strictly speaking, you get into undefined beahviour territory.
                                Presicely because of the very paragraph you quote above.

                                --
                                Gabriel Dos Reis
                                gdr@integrable-solutions.net

                                [ See http://www.gotw.ca/resources/clcm.htm for info about ]
                                [ comp.lang.c++.m oderated. First time posters: Do this! ]

                                Comment

                                Working...