namespace problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?ISO-8859-15?Q?Sebastian_Pf=FCtzner?=

    namespace problem

    Hi,

    the following code produces errors with VC++ and Comeau, but compiles
    with g++:

    #include <iostream>

    namespace n
    {
    struct c
    {
    void test();

    private:
    struct s
    {
    int i;
    };

    friend void f(s t);
    };
    }

    void n::c::test()
    {
    s t = {42};
    f(t);
    }

    void n::f(c::s t)
    {
    std::cout << t.i << std::endl;
    }

    int main()
    {
    n::c().test();
    }

    comeau prints:
    error: namespace "n" has no member "f"

    vc++ prints:
    error C2248: 'n::c::s' cannot access private struct declared in class 'n::c'

    both point to the line 'void n::f(c::s t)'.

    If I write:

    namespace n
    {
    void f(c::s t)
    {
    std::cout << t.i << std::endl;
    }
    }

    instead, everything works fine.
    What is wrong with the first version?

    Thanks in advance
    --
    Sebastian Pfützner
    s.pfuetzner@onl inehome.de
    ICQ-ID: 39965036
  • Barry

    #2
    Re: namespace problem

    On Sep 26, 4:43 pm, Sebastian Pfützner <s.pfuetz...@on linehome.de>
    wrote:
    Hi,
    >
    the following code produces errors with VC++ and Comeau, but compiles
    with g++:
    >
    #include <iostream>
    >
    namespace n
    {
         struct c
         {
             void test();
    >
         private:
             struct s
             {
                 int i;
             };
    >
             friend void f(s t);
         };
    >
    }
    >
    void n::c::test()
    {
         s t = {42};
         f(t);
    >
    }
    >
    void n::f(c::s t)
    {
         std::cout << t.i << std::endl;
    >
    }
    void n::f(n::c::s t)
    {
    ...
    }

    If I don't miss something, then the code above should work,
    But anyway, my gcc (4.3), cl (8.0) both fails to compile again.

    >
    int main()
    {
         n::c().test();
    >
    }
    >
    comeau prints:
    error: namespace "n" has no member "f"
    >
    vc++ prints:
    error C2248: 'n::c::s' cannot access private struct declared in class 'n::c'
    >
    both point to the line 'void n::f(c::s t)'.
    >
    If I write:
    >
    namespace n
    {
         void f(c::s t)
         {
             std::cout << t.i << std::endl;
         }
    >
    }
    >
    instead, everything works fine.
    What is wrong with the first version?
    >
    Thanks in advance
    I think there's both versions should work, as long as
    the modification I mentioned above.

    I guess this is due to bugs with gcc and vc.

    --
    Best Regards
    Barry

    Comment

    • =?ISO-8859-1?Q?Sebastian_Pf=FCtzner?=

      #3
      Re: namespace problem

      Barry schrieb:
      I think there's both versions should work, as long as
      the modification I mentioned above.
      >
      I guess this is due to bugs with gcc and vc.
      gcc works for me, but Comeau online fails. So there is a bug in Comeau too?

      --
      Sebastian Pfützner
      s.pfuetzner@onl inehome.de
      ICQ-ID: 39965036

      Comment

      • =?UTF-8?B?5Lmm5ZGG5b2t?=

        #4
        Re: namespace problem

        Sebastian Pfützner 写道:
        Hi,

        the following code produces errors with VC++ and Comeau, but compiles
        with g++:

        #include <iostream>

        namespace n
        {
        struct c
        {
        void test();

        private:
        struct s
        {
        int i;
        };

        friend void f(s t);
        };
        }

        void n::c::test()
        {
        s t = {42};
        f(t);
        }

        void n::f(c::s t)
        {
        std::cout << t.i << std::endl;
        }

        int main()
        {
        n::c().test();
        }

        comeau prints:
        error: namespace "n" has no member "f"

        vc++ prints:
        error C2248: 'n::c::s' cannot access private struct declared in class
        'n::c'

        both point to the line 'void n::f(c::s t)'.

        If I write:

        namespace n
        {
        void f(c::s t)
        {
        std::cout << t.i << std::endl;
        }
        }

        instead, everything works fine.
        What is wrong with the first version?

        Thanks in advance
        f should be declared before its implementation as it in the namespace.
        i don't have VC on my PC, so the following is just what i thought to be right,so i am not sure it works with VC
        you just try this.

        Good luck.

        namespace n
        {
        struct c
        {

        private:
        struct s
        {
        ...
        };
        friend void f(c::s t);
        ...
        }

        void f(c::s t);
        }

        void n:f(c::s t)
        {
        std::cout << t.i << std::endl;
        }

        int main()
        {
        ...
        }

        Comment

        • =?ISO-8859-15?Q?Sebastian_Pf=FCtzner?=

          #5
          Re: namespace problem

          Michael DOUBEZ schrieb:
          f(s) is never declared into n. You can also write:
          >
          namespace n
          {
          void f(c::s t);
          }
          >
          >
          void n::f(c::s t)
          {
          .....
          }
          No, it doesn't compile in comeau if I add the declaration.
          --
          Sebastian Pfützner
          s.pfuetzner@onl inehome.de
          ICQ-ID: 39965036

          Comment

          • =?UTF-8?B?U2ViYXN0aWFuIFBmw7x0em5lcg==?=

            #6
            Re: namespace problem

            书呆彭 schrieb:
            f should be declared before its implementation as it in the namespace.
            i don't have VC on my PC, so the following is just what i thought to be
            right,so i am not sure it works with VC
            you just try this.
            >
            Good luck.
            >
            namespace n
            {
            struct c
            {
            >
            private:
            struct s
            {
            ...
            };
            friend void f(c::s t);
            ...
            }
            >
            void f(c::s t);
            }
            >
            void n:f(c::s t)
            {
            std::cout << t.i << std::endl;
            }
            >
            int main()
            {
            ...
            }
            This doesn't fix the problem, here the complete code with declaration of f:

            #include <iostream>

            namespace n
            {
            struct c
            {
            void test();

            private:
            struct s
            {
            int i;
            };

            friend void f(s t);
            };

            void f(c::s t);
            }

            void n::c::test()
            {
            s t = {42};
            f(t);
            }

            void n::f(c::s t)
            {
            std::cout << t.i << std::endl;
            }

            int main()
            {
            n::c().test();
            }

            --
            Sebastian Pfützner
            s.pfuetzner@onl inehome.de
            ICQ-ID: 39965036

            Comment

            • Victor Bazarov

              #7
              Re: namespace problem

              Sebastian Pfützner wrote:
              [..] here the complete code with declaration of f:
              >
              #include <iostream>
              >
              namespace n
              {
              struct c
              {
              void test();
              >
              private:
              struct s
              {
              int i;
              };
              >
              friend void f(s t);
              };
              >
              void f(c::s t);
              }
              >
              void n::c::test()
              {
              s t = {42};
              f(t);
              }
              >
              void n::f(c::s t)
              {
              std::cout << t.i << std::endl;
              }
              >
              int main()
              {
              n::c().test();
              }
              >
              I think you should ask Comeau folks for the explanation. They have a
              link on their site to send a question to the compiler team, use it.

              As I could understand from 3.3.1/6 (it's a note, hence non-normative,
              but it explains the other elements), the name 'f' should be considered a
              member of 'n', although it doesn't *introduce* that name (and that's why
              you need the extra declaration to be able to use 'f' later). So the
              compiler *should* connect the 'f' from the 'friend' declaration with the
              'f' from the namespace declaration and *merge* them because, according
              to the Standard (at least how I understand it) they declare the *same*
              function.

              Do ask Comeau, and then post again with any resolution. Thanks for this
              interesting question!

              V
              --
              Please remove capital 'A's when replying by e-mail
              I do not respond to top-posted replies, please don't ask

              Comment

              • Ali Karaali

                #8
                Re: namespace problem

                I think you should ask Comeau folks for the explanation.  They have a
                link on their site to send a question to the compiler team, use it.
                >
                As I could understand from 3.3.1/6 (it's a note, hence non-normative,
                but it explains the other elements), the name 'f' should be considered a
                member of 'n', although it doesn't *introduce* that name (and that's why
                you need the extra declaration to be able to use 'f' later).  So the
                compiler *should* connect the 'f' from the 'friend' declaration with the
                'f' from the namespace declaration and *merge* them because, according
                to the Standard (at least how I understand it) they declare the *same*
                function.
                void fonk (); // <-- Why do I have to declare it in here?

                /* If I don't declare it,
                #error `void fonk()' should have been declared inside `::'
                */

                namespace MySpace
                {
                int a = 1, b = 2, c = 3;

                class Sample
                {
                int m_s;

                public :
                Sample()
                :
                m_s( 0 )
                {};

                int getSample()
                {
                return this->m_s;
                }

                friend void ::fonk();
                };

                int foo (Sample sample)
                {
                return sample.getSampl e();
                }

                int func (int arg)
                {
                return arg * arg;
                }
                }

                void fonk ()
                {
                MySpace::Sample sample;

                cout << sample.m_s << " " << 5 << endl;
                cout << "I am a friend";
                }

                Comment

                • Victor Bazarov

                  #9
                  Re: namespace problem

                  Ali Karaali wrote:
                  >I think you should ask Comeau folks for the explanation. They have a
                  >link on their site to send a question to the compiler team, use it.
                  >>
                  >As I could understand from 3.3.1/6 (it's a note, hence non-normative,
                  >but it explains the other elements), the name 'f' should be considered a
                  >member of 'n', although it doesn't *introduce* that name (and that's why
                  >you need the extra declaration to be able to use 'f' later). So the
                  >compiler *should* connect the 'f' from the 'friend' declaration with the
                  >'f' from the namespace declaration and *merge* them because, according
                  >to the Standard (at least how I understand it) they declare the *same*
                  >function.
                  >
                  void fonk (); // <-- Why do I have to declare it in here?
                  >
                  /* If I don't declare it,
                  #error `void fonk()' should have been declared inside `::'
                  Which line does it refer to? To the 'friend' declaration?
                  */
                  >
                  namespace MySpace
                  {
                  int a = 1, b = 2, c = 3;
                  >
                  class Sample
                  {
                  int m_s;
                  >
                  public :
                  Sample()
                  :
                  m_s( 0 )
                  {};
                  >
                  int getSample()
                  {
                  return this->m_s;
                  }
                  >
                  friend void ::fonk();
                  I believe the reason the compiler needs 'fonk' declared in the global
                  namespace before you declare it here is due to your use of scope
                  resolution. If you didn't use it, the name would be looked up in the
                  namespace surrounding your class, and if the function isn't found, it
                  would be considered "forward declared" for the purposes of that class
                  definition only. But since you specified where to look for the function
                  by using '::', the compiler has to look and it doesn't find it.
                  };
                  >
                  int foo (Sample sample)
                  {
                  return sample.getSampl e();
                  }
                  >
                  int func (int arg)
                  {
                  return arg * arg;
                  }
                  }
                  >
                  void fonk ()
                  {
                  MySpace::Sample sample;
                  >
                  cout << sample.m_s << " " << 5 << endl;
                  cout << "I am a friend";
                  }
                  V
                  --
                  Please remove capital 'A's when replying by e-mail
                  I do not respond to top-posted replies, please don't ask

                  Comment

                  • Ali Karaali

                    #10
                    Re: namespace problem

                    class Sample
                    {
                    int m_s;

                    public :
                    Sample()
                    :
                    m_s( 0 )
                    {};

                    int getSample()
                    {
                    return this->m_s;
                    }

                    friend void fonk();
                    };

                    int foo (Sample sample)
                    {
                    return sample.getSampl e();
                    }

                    When the namespace dropped, everything is fine. And you don't have to
                    use forward declaration. As I know, the friend decleration in a class
                    means a function prototype. As you see the above. But when we put the
                    namespace, it don't work.

                    I really don't understand why does the compiler need the forward
                    decleration when we put the namespace?

                    namespace MySpace
                    {
                    class Sample
                    {
                    int m_s;

                    public :
                    Sample()
                    :
                    m_s( 0 )
                    {};

                    int getSample()
                    {
                    return this->m_s;
                    }

                    friend void ::fonk();
                    };
                    }

                    void fonk ()
                    {
                    MySpace::Sample sample;

                    cout << sample.m_s << " " << 5 << endl;
                    cout << "I am a friend";
                    }

                    Comment

                    • Victor Bazarov

                      #11
                      Re: namespace problem

                      Ali Karaali wrote:
                      class Sample
                      {
                      int m_s;
                      >
                      public :
                      Sample()
                      :
                      m_s( 0 )
                      {};
                      >
                      int getSample()
                      {
                      return this->m_s;
                      }
                      >
                      friend void fonk();
                      };
                      >
                      int foo (Sample sample)
                      {
                      return sample.getSampl e();
                      }
                      >
                      When the namespace dropped, everything is fine.
                      Add the scope resolution in front of 'fonk' making it '::fonk', does it
                      work now? It's not the presence or absence of the namespace, it's the
                      qualified versus unqualified name. See 3.4.3/4. "The name shall be
                      declared or shall be a name whose declara-tion is visible in global
                      scope because of a using-directive".
                      And you don't have to
                      use forward declaration. As I know, the friend decleration in a class
                      means a function prototype.
                      No, it does not. Not for the means of using that function outside of
                      the class itself.
                      As you see the above. But when we put the
                      namespace, it don't work.
                      You make more than one change. You put in the namespace and change the
                      syntax in the 'friend' declaration itself. That what gets you confused.
                      >
                      I really don't understand why does the compiler need the forward
                      decleration when we put the namespace?
                      >
                      namespace MySpace
                      {
                      class Sample
                      {
                      int m_s;
                      >
                      public :
                      Sample()
                      :
                      m_s( 0 )
                      {};
                      >
                      int getSample()
                      {
                      return this->m_s;
                      }
                      >
                      friend void ::fonk();
                      };
                      }
                      >
                      void fonk ()
                      {
                      MySpace::Sample sample;
                      >
                      cout << sample.m_s << " " << 5 << endl;
                      cout << "I am a friend";
                      }

                      --
                      Please remove capital 'A's when replying by e-mail
                      I do not respond to top-posted replies, please don't ask

                      Comment

                      • Ali Karaali

                        #12
                        Re: namespace problem

                        Add the scope resolution in front of 'fonk' making it '::fonk', does it
                        work now?  It's not the presence or absence of the namespace, it's the
                        qualified versus unqualified name.  See 3.4.3/4.  "The name shall be
                        declared or shall be a name whose declara-tion is visible in global
                        scope because of a using-directive".
                        I know but;

                        namespace MySpace
                        {
                        class Sample
                        {
                        int m_s;

                        public :

                        Sample()
                        :
                        m_s( 0 )
                        {};

                        friend void ::fonk();
                        /* I put scope resolution in front of 'fonk'
                        because fonk is a global function.
                        The funk needs a forward declaration.
                        Why?
                        */

                        friend void foo();
                        /* I didn't put scope resolution because
                        foo defined in the MySpace
                        The foo doesn't need a forward declaration
                        */
                        };

                        void foo()
                        {
                        MySpace::Sample sample;

                        cout << sample.m_s << " " << 5 << endl;
                        cout << "I am a friend";
                        }
                        }

                        void fonk ()
                        {
                        MySpace::Sample sample;

                        cout << sample.m_s << " " << 5 << endl;
                        cout << "I am a friend";
                        }

                        Comment

                        • Victor Bazarov

                          #13
                          Re: namespace problem

                          Ali Karaali wrote:
                          >Add the scope resolution in front of 'fonk' making it '::fonk', does it
                          >work now? It's not the presence or absence of the namespace, it's the
                          >qualified versus unqualified name. See 3.4.3/4. "The name shall be
                          >declared or shall be a name whose declara-tion is visible in global
                          >scope because of a using-directive".
                          >
                          I know but;
                          >
                          namespace MySpace
                          {
                          class Sample
                          {
                          int m_s;
                          >
                          public :
                          >
                          Sample()
                          :
                          m_s( 0 )
                          {};
                          >
                          friend void ::fonk();
                          /* I put scope resolution in front of 'fonk'
                          because fonk is a global function.
                          The funk needs a forward declaration.
                          Why?
                          OK. Let me repeat. See 3.4.3/4. "The name shall be declared.. ". OK,
                          maybe this is easier to grok: *because the Standard says* it must be
                          declared. Get it now?
                          */
                          >
                          friend void foo();
                          /* I didn't put scope resolution because
                          foo defined in the MySpace
                          The foo doesn't need a forward declaration
                          */
                          Sigh... Put 'MySpace::' in front of 'foo' and see it fail. If you
                          don't get it after this, I give up!
                          };
                          >
                          void foo()
                          {
                          MySpace::Sample sample;
                          >
                          cout << sample.m_s << " " << 5 << endl;
                          cout << "I am a friend";
                          }
                          }
                          >
                          void fonk ()
                          {
                          MySpace::Sample sample;
                          >
                          cout << sample.m_s << " " << 5 << endl;
                          cout << "I am a friend";
                          }
                          V
                          --
                          Please remove capital 'A's when replying by e-mail
                          I do not respond to top-posted replies, please don't ask

                          Comment

                          • Ali Karaali

                            #14
                            Re: namespace problem

                            Sigh...  Put 'MySpace::' in front of 'foo' and see it fail.  If you
                            don't get it after this, I give up!

                            namespace MySpace
                            {
                            class Sample
                            {
                            int m_s;

                            public :
                            Sample()
                            :
                            m_s( 0 )
                            {};

                            friend void MySpace::foo();
                            };

                            void foo()
                            {
                            MySpace::Sample sample;

                            cout << sample.m_s << " " << 5 << endl;
                            cout << "I am a friend";
                            }
                            }

                            It worked fine....

                            Comment

                            • Victor Bazarov

                              #15
                              Re: namespace problem

                              Ali Karaali wrote:
                              >Sigh... Put 'MySpace::' in front of 'foo' and see it fail. If you
                              >don't get it after this, I give up!
                              >
                              >
                              namespace MySpace
                              {
                              class Sample
                              {
                              int m_s;
                              >
                              public :
                              Sample()
                              :
                              m_s( 0 )
                              {};
                              >
                              friend void MySpace::foo();
                              };
                              >
                              void foo()
                              {
                              MySpace::Sample sample;
                              >
                              cout << sample.m_s << " " << 5 << endl;
                              cout << "I am a friend";
                              }
                              }
                              >
                              It worked fine....
                              Contact the compiler creators and ask them for the clarification.
                              Looks to me like a defect in the compiler.

                              V
                              --
                              Please remove capital 'A's when replying by e-mail
                              I do not respond to top-posted replies, please don't ask

                              Comment

                              Working...