Topic: Scope of friends defined in classes


Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Wed, 15 Dec 2004 00:53:18 GMT
Raw View
""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote in message
news:qjIud.245775$R05.129920@attbi_s53...
[snip]
> > What that means is that the body of the function can refer to other
> > members of M, even though f itself is injected into the scope
surrounding
> > M.
>
> Let me get this straight.  It would seem that only static members and
types
> declared in M would actually be the members that function can refer to,
yes?
> And "car refer" probably means that it doesn't need to qualify those
names,
> is that correct?  IOW,
>
>     class M {
>         typedef int blah;
>         class MM {};
>         static double d;
>         static void foo();
>
>         friend void f() {
>             blah b; // uses M::blah without 'M::'
>             MM mm;  //   *******
>             d = 3.14;
>             foo();   // calls M::foo  ********
>         }
>     };
>
> One thing is a bit unclear.  What if there is '::foo'?  Or '::MM'?  Which
> ones
> will be used on the lines marked with asterisks, 'M::' or '::'?

Why is it unclear - surely the usual scope rules apply so MM means M::MM ?

Roger Orr
--
MVP in C++ at www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Wed, 15 Dec 2004 05:39:22 GMT
Raw View
"Roger Orr" <rogero@howzatt.demon.co.uk> wrote...
> ""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote in message
> news:qjIud.245775$R05.129920@attbi_s53...
> [snip]
>> > What that means is that the body of the function can refer to other
>> > members of M, even though f itself is injected into the scope
> surrounding
>> > M.
>>
>> Let me get this straight.  It would seem that only static members and
> types
>> declared in M would actually be the members that function can refer to,
> yes?
>> And "car refer" probably means that it doesn't need to qualify those
> names,
>> is that correct?  IOW,
>>
>>     class M {
>>         typedef int blah;
>>         class MM {};
>>         static double d;
>>         static void foo();
>>
>>         friend void f() {
>>             blah b; // uses M::blah without 'M::'
>>             MM mm;  //   *******
>>             d = 3.14;
>>             foo();   // calls M::foo  ********
>>         }
>>     };
>>
>> One thing is a bit unclear.  What if there is '::foo'?  Or '::MM'?  Which
>> ones
>> will be used on the lines marked with asterisks, 'M::' or '::'?
>
> Why is it unclear - surely the usual scope rules apply so MM means M::MM ?

OK, so, 'being in lexical scope' defines how names used inside the function
are resolved, first the innermost scope, then outer, etc., right?  Also, the
function arguments are in the scope too, right?  So, this:

  class M {
     typedef int blah;
     friend void foo(blah b) { b + 42; }
  };

  void foo(int);

  int main() {
     foo(33);
  }

is a valid program, correct?  OK, Comeau compiles fine.  Now, this one:

  class M {
     typedef int blah;
     friend void foo(blah b) { b + 42; }
  public:
     static void bar() { foo(33); } // line 5
  };

  int main() {
     M::bar();
  }

Causes the error

"ComeauTest.c", line 5: error: identifier "foo" is undefined
       static void bar() { foo(33); } // line 5
                           ^

V

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Thu, 16 Dec 2004 04:57:32 GMT
Raw View
""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote in message
news:ngNvd.187201$5K2.43852@attbi_s03...
> "Roger Orr" <rogero@howzatt.demon.co.uk> wrote...
[snip]
> OK, so, 'being in lexical scope' defines how names used inside the
function
> are resolved, first the innermost scope, then outer, etc., right?  Also,
the
> function arguments are in the scope too, right?  So, this:
>
>   class M {
>      typedef int blah;
>      friend void foo(blah b) { b + 42; }
>   };
>
>   void foo(int);
>
>   int main() {
>      foo(33);
>   }
>
> is a valid program, correct?  OK, Comeau compiles fine.  Now, this one:
>
>   class M {
>      typedef int blah;
>      friend void foo(blah b) { b + 42; }
>   public:
>      static void bar() { foo(33); } // line 5
>   };
>
>   int main() {
>      M::bar();
>   }
>
> Causes the error
>
> "ComeauTest.c", line 5: error: identifier "foo" is undefined
>        static void bar() { foo(33); } // line 5
>                            ^

I think this is a bug. But I always worry when I disagree with Comeau...

15.4p7: A name nominated by a friend declaration shall be accessible in the
scope of the class containing the friend declaration.

Roger Orr
--
MVP in C++ at www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@lhup.edu (John Potter)
Date: Thu, 16 Dec 2004 20:50:48 GMT
Raw View
On Thu, 16 Dec 2004 04:57:32 GMT, rogero@howzatt.demon.co.uk ("Roger
Orr") wrote:

> ""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote in message
> news:ngNvd.187201$5K2.43852@attbi_s03...

> >   class M {
> >      typedef int blah;
> >      friend void foo(blah b) { b + 42; }
> >   public:
> >      static void bar() { foo(33); } // line 5
> >   };
> >   int main() {
> >      M::bar();
> >   }

> > Causes the error

> > "ComeauTest.c", line 5: error: identifier "foo" is undefined
> >        static void bar() { foo(33); } // line 5
> >                            ^

> I think this is a bug. But I always worry when I disagree with Comeau...

> 15.4p7: A name nominated by a friend declaration shall be accessible in the
> scope of the class containing the friend declaration.

I think you may be missing the meaning of "shall".  It says that the
name nominated "shall" be accessible not that it "will become".  It
prevents nominating a private member of another class as a friend
because that would not be accessible.

It is also not found by ADL because 33 is just an int.  Add a
declaration of foo before the class and it will compile.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Victor Bazarov <v.Abazarov@comAcast.net>
Date: Thu, 16 Dec 2004 16:50:54 CST
Raw View
John Potter wrote:
> On Thu, 16 Dec 2004 04:57:32 GMT, rogero@howzatt.demon.co.uk ("Roger
> Orr") wrote:
>
>
>>""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote in message
>>news:ngNvd.187201$5K2.43852@attbi_s03...
>
>
>>>  class M {
>>>     typedef int blah;
>>>     friend void foo(blah b) { b + 42; }
>>>  public:
>>>     static void bar() { foo(33); } // line 5
>>>  };
>>>  int main() {
>>>     M::bar();
>>>  }
>
>
>>>Causes the error
>
>
>>>"ComeauTest.c", line 5: error: identifier "foo" is undefined
>>>       static void bar() { foo(33); } // line 5
>>>                           ^
>
>
>>I think this is a bug. But I always worry when I disagree with Comeau...
>
>
>>15.4p7: A name nominated by a friend declaration shall be accessible in the

11.4p7  (got me a minute to locate it :-)

>>scope of the class containing the friend declaration.
>
>
> I think you may be missing the meaning of "shall".  It says that the
> name nominated "shall" be accessible not that it "will become".  It
> prevents nominating a private member of another class as a friend
> because that would not be accessible.
>
> It is also not found by ADL because 33 is just an int.  Add a
> declaration of foo before the class and it will compile.

That sounds reasonable, thank you, John.  But now I have more questions.

What would be the point of defining a friend inside the class definition
if you cannot call it without having at least declared it outside _before_
the class definition?  And how to fit this {"shall" versus "will become"}
explanation with a simple notion that every definition of a function is
also a declaration (3.1/2)?  Or is it enough that 11.4 basically says that
a friend definition inside is _not_ a declaration (although without using
these particular words)?

I started reading 11.4/5 again and noticed these words: "and the function
has namespace scope".  What does that mean?  If the name is unqualified,
what other scope is there?  Or does it mean that the function name has to
be already known by the time the compiler encounters the definition [of
the friend function inside the class]?

Thanks again.

Victor

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rogero@howzatt.demon.co.uk
Date: Sat, 18 Dec 2004 19:58:33 CST
Raw View
Victor Bazarov wrote:
> John Potter wrote:
> > "Roger Orr") wrote:
> >>""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote
> >
> >>>  class M {
> >>>     typedef int blah;
> >>>     friend void foo(blah b) { b + 42; }
> >>>  public:
> >>>     static void bar() { foo(33); } // line 5
> >>>  };
> >>>  int main() {
> >>>     M::bar();
> >>>  }
> >
> >>>"ComeauTest.c", line 5: error: identifier "foo" is undefined
> >>>       static void bar() { foo(33); } // line 5
> >>>                           ^
> >
> >>I think this is a bug. But I always worry when I disagree with
Comeau...
> >
> >
> >>15.4p7: A name nominated by a friend declaration shall be
accessible in the
>
> 11.4p7  (got me a minute to locate it :-)

Sorry :-)

> >>scope of the class containing the friend declaration.
> >
> > I think you may be missing the meaning of "shall".  It says that
the
> > name nominated "shall" be accessible not that it "will become".  It
> > prevents nominating a private member of another class as a friend
> > because that would not be accessible.

Looks like I was getting too tired to concentrate - thanks for your
input, John!

> What would be the point of defining a friend inside the class
definition
> if you cannot call it without having at least declared it outside
_before_
> the class definition?

There is a point -- if you call the function using ADL.  I suspect the
principal usage is for friend operators.

class X
{
friend X operator+( int, X ) { /* ... */ }
};

then
X x1;
X x2;

x1 = 1 + x2;

> And how to fit this {"shall" versus "will become"}
> explanation with a simple notion that every definition of a function
is
> also a declaration (3.1/2)?  Or is it enough that 11.4 basically says
that
> a friend definition inside is _not_ a declaration (although without
using
> these particular words)?

I still think (despite having misread the paragraph) that the
definition
should be a declaration - at least as far as 'M' is concerned.
If this is not the case then I think it must be made clearer in the
standard.

> I started reading 11.4/5 again and noticed these words: "and the
function
> has namespace scope".  What does that mean?  If the name is
unqualified,
> what other scope is there?  Or does it mean that the function name
has to
> be already known by the time the compiler encounters the definition
[of
> the friend function inside the class]?

It may mean that the function cannot be a member function of an outer
class:

class X
{
void f();
class Y
{
friend void f() { /* illegal? */ }
};
};

Returning to the original code,
should it compile if the static member function became:

static void bar() {
void foo( blah );
foo(33); }

(Comeau at any rate likes it)
HTH
Roger Orr
--
MVP in C++ at www.brainbench.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@lhup.edu (John Potter)
Date: Tue, 21 Dec 2004 23:04:31 GMT
Raw View
On Sat, 18 Dec 2004 19:58:33 CST, rogero@howzatt.demon.co.uk wrote:

> Victor Bazarov wrote:
> > John Potter wrote:
> > > "Roger Orr") wrote:
> > >>""Victor Bazarov"" <v.Abazarov@comAcast.net> wrote
> > >
> > >>>  class M {
> > >>>     typedef int blah;
> > >>>     friend void foo(blah b) { b + 42; }
> > >>>  public:
> > >>>     static void bar() { foo(33); } // line 5
> > >>>  };
> > >>>  int main() {
> > >>>     M::bar();
> > >>>  }

[snip]

> > And how to fit this {"shall" versus "will become"}
> > explanation with a simple notion that every definition of a function
> is
> > also a declaration (3.1/2)?  Or is it enough that 11.4 basically says
> that
> > a friend definition inside is _not_ a declaration (although without
> using
> > these particular words)?

> I still think (despite having misread the paragraph) that the
> definition
> should be a declaration - at least as far as 'M' is concerned.
> If this is not the case then I think it must be made clearer in the
> standard.

The rules were changed along the road to standardization.  The
definition is a declaration; however, the name is not injected
into the enclosing namespace as it once was.  It seemed inappropriate
for the class to inject a name outward.  If there is a declaration
in the enclosing namespace, it is a declaration of this defined
function and makes the name visible in that namespace.

> > I started reading 11.4/5 again and noticed these words: "and the
> function
> > has namespace scope".  What does that mean?  If the name is
> unqualified,
> > what other scope is there?  Or does it mean that the function name
> has to
> > be already known by the time the compiler encounters the definition
> [of
> > the friend function inside the class]?

> It may mean that the function cannot be a member function of an outer
> class:

Yes.

> class X
> {
> void f();
> class Y
> {
> friend void f() { /* illegal? */ }
> };
> };

It appears from compilers that it is not illegal.  I guess that we must
read the above to mean that the function has namespace scope regardless
of the outer class function of the same name.

> Returning to the original code,
> should it compile if the static member function became:

> static void bar() {
> void foo( blah );
> foo(33); }

> (Comeau at any rate likes it)

Yes.  That declaration of foo is like any other declaration of an
enclosing namespace function.  It makes no difference whether it
is in the member function or the namespace.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Usenet@aristeia.com (Scott Meyers)
Date: Fri, 10 Dec 2004 22:56:11 GMT
Raw View
It would not surprise me if this has been hashed over before, but I was
unable to unearth anything via Google.  Feel free to respond with a URL if
this is an old topic.

11.4/5 says:

  A function can be defined in a friend declaration of a class if and only if
  the class is a non-local class (9.8), the function name is unqualified, and
  the function has namespace scope. [Example:

    class M {
    friend void f() { }  // definition of global f, a friend of M,
                         // not the definition of a member function
    };

  end example] Such a function is implicitly inline. A friend function
  defined in a class is in the (lexical) scope of the class in which it is
  defined. A friend function defined outside the class is not (3.4.1).

This suggests to me that this should not compile:

  class M { ... };      // as above

  int main()
  {
    f();                // should not compile;  though f is global, it's
  }                     // in the lexical scope of M

Two of my compilers agree with me.  However, 11.4/5 also suggests to me
that the following SHOULD compile:

  class M {
    friend void f(){}   // as before
    static void g()
    { f(); }            // should compile:  call to (global) f from within
  };                    // the lexical scope of M

Both compilers disagree with me.

Who's right, and why?

Thanks,

Scott

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Sat, 11 Dec 2004 09:47:27 GMT
Raw View
"Scott Meyers" <Usenet@aristeia.com> wrote...
> It would not surprise me if this has been hashed over before, but I was
> unable to unearth anything via Google.  Feel free to respond with a URL if
> this is an old topic.

I've found quite a few discussions on friends defined in a class definition,
not sure which ones you'd like to see.

Try http://tinyurl.com/62lna

Also, see 7.3.1.2/3  Since a definition is also a declaration, that applies,
AFAICT.  To be used outside the class the function has to be declared
outside
that class.

> 11.4/5 says:
>
>  A function can be defined in a friend declaration of a class if and only
> if
>  the class is a non-local class (9.8), the function name is unqualified,
> and
>  the function has namespace scope. [Example:
>
>    class M {
>    friend void f() { }  // definition of global f, a friend of M,
>                         // not the definition of a member function
>    };
>
>  end example] Such a function is implicitly inline. A friend function
>  defined in a class is in the (lexical) scope of the class in which it is
>  defined. A friend function defined outside the class is not (3.4.1).
>
> This suggests to me that this should not compile:
>
>  class M { ... };      // as above
>
>  int main()
>  {
>    f();                // should not compile;  though f is global, it's
>  }                     // in the lexical scope of M
>
> Two of my compilers agree with me.  However, 11.4/5 also suggests to me
> that the following SHOULD compile:
>
>  class M {
>    friend void f(){}   // as before
>    static void g()
>    { f(); }            // should compile:  call to (global) f from within
>  };                    // the lexical scope of M
>
> Both compilers disagree with me.
>
> Who's right, and why?

I think you're right.

V

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ark@acm.org ("Andrew Koenig")
Date: Sat, 11 Dec 2004 18:07:44 GMT
Raw View
"Scott Meyers" <Usenet@aristeia.com> wrote in message
news:MPG.1c23c6bb17bfdbb59897a9@news.hevanet.com...

> It would not surprise me if this has been hashed over before, but I was
> unable to unearth anything via Google.  Feel free to respond with a URL if
> this is an old topic.
>
> 11.4/5 says:
>
>  A function can be defined in a friend declaration of a class if and only
> if
>  the class is a non-local class (9.8), the function name is unqualified,
> and
>  the function has namespace scope. [Example:
>
>    class M {
>    friend void f() { }  // definition of global f, a friend of M,
>                         // not the definition of a member function
>    };
>
>  end example] Such a function is implicitly inline. A friend function
>  defined in a class is in the (lexical) scope of the class in which it is
>  defined. A friend function defined outside the class is not (3.4.1).

What that means is that the body of the function can refer to other members
of M, even though f itself is injected into the scope surrounding M.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Usenet@aristeia.com (Scott Meyers)
Date: Sun, 12 Dec 2004 19:04:14 GMT
Raw View
Relatedly, I'm trying to figure out what it means for a function to be
global, but in the lexical scope of a class.  Consider the example again
from 11.4/5:

 class M {
    friend void f() { }  // definition of global f, a friend of M,
                         // not the definition of a member function
    };

f is global, so that suggests that trying to define another f at global
scope should be invalid.  But the f above is in the lexical scope of M,
and that suggests that defining another f in the global lexical scope
might be okay.  But maybe that would be an ODR violation that does not
require a diagnostic...

So should this compile?

  class M {
    friend void f() { }  // f is globol, but in M's lexical scope
  };

  void f() { int x; }    // f is global, but in the global lexical scope

VC7.1, g++ 3.2, and Comeau 4.3.3 all say no, complaining that f is being
redefined.  Are they correct?

Scott




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Mon, 13 Dec 2004 08:38:17 GMT
Raw View
Scott Meyers wrote:
> Relatedly, I'm trying to figure out what it means for a function to be
> global, but in the lexical scope of a class.  Consider the example again
> from 11.4/5:
>
>  class M {
>     friend void f() { }  // definition of global f, a friend of M,
>                          // not the definition of a member function
>     };
>
> f is global, so that suggests that trying to define another f at global
> scope

mith the same arguments.

> should be invalid.  But the f above is in the lexical scope of M,
> and that suggests that defining another f in the global lexical scope
> might be okay.

It's not.

> But maybe that would be an ODR violation that does not
> require a diagnostic...
>
> So should this compile?
>
>   class M {
>     friend void f() { }  // f is globol, but in M's lexical scope
>   };
>
>   void f() { int x; }    // f is global, but in the global lexical scope
>
> VC7.1, g++ 3.2, and Comeau 4.3.3 all say no, complaining that f is being
> redefined.  Are they correct?

Yes they are.

HTH,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net ("Victor Bazarov")
Date: Mon, 13 Dec 2004 08:37:55 GMT
Raw View
"Andrew Koenig" <ark@acm.org> wrote...
> "Scott Meyers" <Usenet@aristeia.com> wrote in message
> news:MPG.1c23c6bb17bfdbb59897a9@news.hevanet.com...
>
>> It would not surprise me if this has been hashed over before, but I was
>> unable to unearth anything via Google.  Feel free to respond with a URL
>> if
>> this is an old topic.
>>
>> 11.4/5 says:
>>
>>  A function can be defined in a friend declaration of a class if and only
>> if
>>  the class is a non-local class (9.8), the function name is unqualified,
>> and
>>  the function has namespace scope. [Example:
>>
>>    class M {
>>    friend void f() { }  // definition of global f, a friend of M,
>>                         // not the definition of a member function
>>    };
>>
>>  end example] Such a function is implicitly inline. A friend function
>>  defined in a class is in the (lexical) scope of the class in which it is
>>  defined. A friend function defined outside the class is not (3.4.1).
>
> What that means is that the body of the function can refer to other
> members of M, even though f itself is injected into the scope surrounding
> M.

Let me get this straight.  It would seem that only static members and types
declared in M would actually be the members that function can refer to, yes?
And "car refer" probably means that it doesn't need to qualify those names,
is that correct?  IOW,

    class M {
        typedef int blah;
        class MM {};
        static double d;
        static void foo();

        friend void f() {
            blah b; // uses M::blah without 'M::'
            MM mm;  //   *******
            d = 3.14;
            foo();   // calls M::foo  ********
        }
    };

One thing is a bit unclear.  What if there is '::foo'?  Or '::MM'?  Which
ones
will be used on the lines marked with asterisks, 'M::' or '::'?

Thank you.

Victor

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]