Language Subtlety or Compiler bug?

Discussion in 'C++' started by Ned Harding, Aug 31, 2004.

  1. Ned Harding

    Ned Harding Guest

    In VC7.1 the following code outputs:
    00000000
    Success!

    It would seem that the Y::eek:perator<< is hiding the global operator<<
    when it is outputting an object from another namespace but not when it
    is outputting an object in the global namespace.

    I can't help but think one of these 2 behaviors is a bug in VC7.1, but
    which one?

    Thanks,

    Ned.




    =========================================
    #include <iostream>

    namespace X
    {
    class Abc1
    {
    };

    }
    std::eek:stream& operator<< (std::eek:stream& strm, const X::Abc1 *node)
    {
    return strm << "Success!";
    }

    X::Abc1 * GetDoc() { return NULL; }

    class Abc2
    {
    };

    Abc2 * GetDoc2() { return NULL; }

    std::eek:stream& operator<< (std::eek:stream& strm, const Abc2 *node)
    {
    return strm << "Success!";
    }

    namespace Y
    {
    std::eek:stream & operator<<(std::eek:stream& a, const char& b)
    {
    return a << "This should not run";
    }

    void DoTest()
    {
    std::cout << GetDoc() << "\n";
    std::cout << GetDoc2() << "\n";
    }
    }



    int main(int argc, char* argv[])
    {
    Y::DoTest();
    return 0;
    }
    Ned Harding, Aug 31, 2004
    #1
    1. Advertising

  2. Ned Harding

    Howard Guest

    "Ned Harding" <> wrote in message
    news:...
    > In VC7.1 the following code outputs:
    > 00000000
    > Success!
    >
    > It would seem that the Y::eek:perator<< is hiding the global operator<<
    > when it is outputting an object from another namespace but not when it
    > is outputting an object in the global namespace.
    >


    I don't see the operator in the Y namespace coming into play at all here.
    What makes you think it is? You're not getting "This should not run" as
    your output. Plus, the operator in Y uses a reference to a char, not a
    pointer - of *any* type!

    > =========================================
    > #include <iostream>
    >
    > namespace X
    > {
    > class Abc1
    > {
    > };
    >
    > }
    > std::eek:stream& operator<< (std::eek:stream& strm, const X::Abc1 *node)
    > {
    > return strm << "Success!";
    > }
    >
    > X::Abc1 * GetDoc() { return NULL; }
    >
    > class Abc2
    > {
    > };
    >
    > Abc2 * GetDoc2() { return NULL; }
    >
    > std::eek:stream& operator<< (std::eek:stream& strm, const Abc2 *node)
    > {
    > return strm << "Success!";
    > }
    >
    > namespace Y
    > {
    > std::eek:stream & operator<<(std::eek:stream& a, const char& b)
    > {
    > return a << "This should not run";
    > }
    >
    > void DoTest()
    > {
    > std::cout << GetDoc() << "\n";
    > std::cout << GetDoc2() << "\n";
    > }
    > }
    >
    >
    >
    > int main(int argc, char* argv[])
    > {
    > Y::DoTest();
    > return 0;
    > }


    It looks to me like your operator in the global namespace is correctly
    getting called for the case where you've passing it an Abc2*. That's normal
    overloading (correct?). In the case where you pass an Abc1*, however, your
    code apparently isn't seeing the overloaded operator that uses an Abc1*, but
    instead is calling the << normally used for a void* pointer.

    I'm no expert on why that is, but if I had to guess (which I do :)), I'd
    say it's because there is nothing specifying that you want to use the
    operator << that's in the X namespace. I'm not even sure how you would do
    that. Perhaps using X:<< ?

    -Howard
    Howard, Aug 31, 2004
    #2
    1. Advertising

  3. Ned Harding

    Howard Guest

    "Howard" <> wrote in message
    news:sC3Zc.537788$Gx4.147573@bgtnsc04-> I'm no expert on why that is, but if
    I had to guess (which I do :)), I'd
    > say it's because there is nothing specifying that you want to use the
    > operator << that's in the X namespace. I'm not even sure how you would do
    > that. Perhaps using X:<< ?
    >


    I meant to say "X::<<" there. (But as I said, it was just a guess. :))

    > -Howard
    >
    >
    Howard, Aug 31, 2004
    #3
  4. Howard wrote:
    > "Howard" <> wrote in message
    > news:sC3Zc.537788$Gx4.147573@bgtnsc04-> I'm no expert on why that is, but if
    > I had to guess (which I do :)), I'd
    >
    >>say it's because there is nothing specifying that you want to use the
    >>operator << that's in the X namespace. I'm not even sure how you would do
    >>that. Perhaps using X:<< ?
    >>

    >
    >
    > I meant to say "X::<<" there. (But as I said, it was just a guess. :))


    I think that :: is allowed only with the name. << is not a name, so it
    probably should be X::eek:perator<<. But I am just adding a guess on top
    of your guess...

    Victor
    Victor Bazarov, Aug 31, 2004
    #4
  5. Ned Harding

    Old Wolf Guest

    (Ned Harding) wrote:
    > In VC7.1 the following code outputs:
    > 00000000
    > Success!
    >
    > It would seem that the Y::eek:perator<< is hiding the global operator<<
    > when it is outputting an object from another namespace but not when it
    > is outputting an object in the global namespace.


    Actually the behaviour is correct.
    Also the Y::eek:perator<< is irrelevant, the code will behave the same
    without it.

    [Abbreviated, equivalent code]:
    > #include <iostream>
    >
    > namespace X { class Abc1 {} };
    >
    > std::eek:stream& operator<< (std::eek:stream& strm, const X::Abc1 *node)
    > { return strm << "Success!"; }
    >
    > class Abc2 { };
    >
    > std::eek:stream& operator<< (std::eek:stream& strm, const Abc2 *node)
    > { return strm << "Success!"; }
    >
    > namespace Y {
    > void DoTest() {
    > std::cout << (X::Abc1 *)0 << "\n";
    > std::cout << (Abc2 *)0 << "\n";
    > }
    > }
    >
    > int main() {
    > Y::DoTest();
    > }


    The first example looks for:
    operator<< (std::eek:stream &, X::Abc1 *)
    in the namespaces 'std' and 'X'. It finds neither.
    It doesn't look in the global namespace because none of its
    parameter types are in the global namespace.

    However there is an implicit conversion (X::Abc1 *) --> (void *)
    so it finds std::eek:perator<<(std::eek:stream &, void *).

    The second example looks for:
    operator<< (std::eek:stream &, ::Abc2 *)
    in the namespace 'std' and the global namespace. It finds
    your std::eek:stream& operator<< (std::eek:stream& strm, const Abc2 *node)
    from the global namespace.

    > namespace Y {
    > std::eek:stream & operator<<(std::eek:stream& a, const char& b)
    > };


    Why did you include that function? It has nothing to do with
    anything else in this program because you never go
    std::cout << (something with char type or convertible to char).
    Old Wolf, Sep 1, 2004
    #5
  6. Ned Harding

    Ned Harding Guest

    (Old Wolf) wrote in message
    > Why did you include that function? It has nothing to do with
    > anything else in this program because you never go
    > std::cout << (something with char type or convertible to char).


    That's the weird part. If you take out Y::eek:perator << (which I agree
    never gets called) then I get

    Success!
    Success!

    I'm not sure why y::eek:perator << is hiding anything, but if it hides
    one of the ::eek:perator<<, why doesn't it hide both?

    ned.
    Ned Harding, Sep 1, 2004
    #6
  7. Ned Harding

    Howard Guest

    "Ned Harding" <> wrote in message
    news:...
    > (Old Wolf) wrote in message
    > > Why did you include that function? It has nothing to do with
    > > anything else in this program because you never go
    > > std::cout << (something with char type or convertible to char).

    >
    > That's the weird part. If you take out Y::eek:perator << (which I agree
    > never gets called) then I get
    >
    > Success!
    > Success!
    >
    > I'm not sure why y::eek:perator << is hiding anything, but if it hides
    > one of the ::eek:perator<<, why doesn't it hide both?
    >
    > ned.


    Try moving the operator that takes the X::Abc1* parameter INSIDE the X
    namespace. Then you won't have any problem.

    BTW, I have no idea how it's possible to "hide" the operator like you've
    described, which I've verified with all kinds of variations of that Y::
    operator. But even though it's never called, it does indeed prevent VC7
    from "seeing" the global namespace operator that takes a parameter type from
    another namespace. But I tend not to sweat stuff like that, once I've found
    a solution! :)

    -Howard
    Howard, Sep 1, 2004
    #7
  8. Ned Harding

    Old Wolf Guest

    (Ned Harding) wrote:
    > (Old Wolf) wrote in message
    > > Why did you include that function? It has nothing to do with
    > > anything else in this program because you never go
    > > std::cout << (something with char type or convertible to char).

    >
    > That's the weird part. If you take out Y::eek:perator << (which I agree
    > never gets called) then I get
    >
    > Success!
    > Success!


    I don't (gcc 3.4.1). Perhaps it is a compiler bug in MSVC.
    (On BCC 5.5.1, both versions give Success! Success!, I suppose it
    looks in the global namespace when it should not.. BCC is not
    famous for its lack of bugs)

    > I'm not sure why y::eek:perator << is hiding anything, but if it hides
    > one of the ::eek:perator<<, why doesn't it hide both?
    Old Wolf, Sep 1, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ed
    Replies:
    24
    Views:
    1,001
    Dimitri Maziuk
    Mar 27, 2006
  2. DaveInSidney
    Replies:
    0
    Views:
    415
    DaveInSidney
    May 9, 2005
  3. Shravani
    Replies:
    8
    Views:
    797
    Bartc
    Mar 16, 2008
  4. john

    compiler bug / strange language feature

    john, Mar 24, 2010, in forum: C Programming
    Replies:
    17
    Views:
    488
    Tim Rentsch
    Mar 27, 2010
  5. Farhad Farzaneh

    Ruby conditionals subtlety?

    Farhad Farzaneh, Feb 18, 2010, in forum: Ruby
    Replies:
    17
    Views:
    212
    Brian Candler
    Feb 21, 2010
Loading...

Share This Page