friend injection: Clarification Required

M

moogyd

Hi,
I am a C++ newbie, and have aa C++ project that compiles with the -
ffriend-injection (g++) option.

I am trying to understand what this option actually does, so that I
can fix the code. Unfortunately, google provides lots of descriptions
based on templates. that are way above my level of understanding.

I therefore created a very simple example:

namespace myNamespace {
class myClass {
friend int compute(myClass arg) {} ;
} ; // myClass
// If compute is not declared here, then I need the g++
// -ffriend-injection option
int compute(myClass arg);
} // myNamespace

int main() {
myNamespace::myClass myVar ;
myNamespace::compute(myVar) ;
return 0 ;
}
This compiles without -ffriend_injection. If I comment the
declaration int compute(..). then the option is required.
Without the namespece, it always compiles.

Therefore, it seems to me that friend injection means that
- all friend functions automatically become visible in the surrounding
namespace (myNamespace in this example)

Is this correct? Can anyone supply a (or a link to) a very simple
explanation.

Thanks,

Steven
 
V

Victor Bazarov

Hi,
I am a C++ newbie, and have aa C++ project that compiles with the -
ffriend-injection (g++) option.

That option is compiler-specific. Consider asking in the g++ newsgroup.
Read on, however.
I am trying to understand what this option actually does, so that I
can fix the code. Unfortunately, google provides lots of descriptions
based on templates. that are way above my level of understanding.

I therefore created a very simple example:

namespace myNamespace {
class myClass {
friend int compute(myClass arg) {} ;
} ; // myClass
// If compute is not declared here, then I need the g++
// -ffriend-injection option
int compute(myClass arg);
} // myNamespace

int main() {
myNamespace::myClass myVar ;
myNamespace::compute(myVar) ;
return 0 ;
}
This compiles without -ffriend_injection. If I comment the
declaration int compute(..). then the option is required.
Without the namespece, it always compiles.

Therefore, it seems to me that friend injection means that
- all friend functions automatically become visible in the surrounding
namespace (myNamespace in this example)

Is this correct? Can anyone supply a (or a link to) a very simple
explanation.

Here is a quote from the current Standard ([class.friend]/5):

"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)."

Note the wording about the scope. If the function is *in* the scope of
the class, it should be found during ADL since your function's argument
is the class that defines that function, but *ONLY* if the function name
is unqualified:

...
int main() {
myNamespace::myClass myVar;
compute(myVar); // unqualified name - found during ADL
}

Since you qualified that name, the ADL doesn't kick in, and the class
scope is not searched, only the namespace scope. Since the function
defined in the class is not *in* the namespace scope (it wasn't declared
there), it is not found.

Now, there are two statements about scope in that paragraph. The first
one says "the function *has* namespace scope" (emphasis mine), which to
me means that *inside* the function the name resolution works from the
namespace scope in which the *class* resides. IOW, if the function had
a name 'foo' in it, and your 'myNamespace' had a 'foo', that 'foo' would
be found.

I don't know *for sure* what your option does, ask in the g++ newsgroup,
but most likely it makes the *name* of the function *available* in the
same namespace as the class (as if it were declared there).

V
 
J

James Kanze

I am a C++ newbie, and have aa C++ project that compiles with the -
ffriend-injection (g++) option.

And not without? I'd be interested in seeing the case where the
absence of friend injection breaks code. (When the committee
removed friend injection, they were convinced that there were no
"reasonable" uses which wouldn't be picked up by ADL.)
I am trying to understand what this option actually does, so
that I can fix the code. Unfortunately, google provides lots
of descriptions based on templates. that are way above my
level of understanding.
I therefore created a very simple example:
namespace myNamespace {
class myClass {
friend int compute(myClass arg) {} ;
} ; // myClass
// If compute is not declared here, then I need the g++
// -ffriend-injection option
int compute(myClass arg);
} // myNamespace
int main() {
myNamespace::myClass myVar ;
myNamespace::compute(myVar) ;
return 0 ;}
This compiles without -ffriend_injection. If I comment the
declaration int compute(..). then the option is required.
Without the namespece, it always compiles.

And if you write simply "compute(myVar)", without the scope
qualifier?
Therefore, it seems to me that friend injection means that
- all friend functions automatically become visible in the surrounding
namespace (myNamespace in this example)
Is this correct?

That's exactly it. In the oldest versions of C++, a function
declared as a friend was "injected" into the nearest surrounding
namespace scope. (In fact, into file scope, because this was
before namespaces.) At some point, it was realized that this
caused some serious problems (I forget what). The committee
looked around for examples where this friend injection was used;
all of the valid examples the committee found were subsumed by
ADL (which had been added much later), so they felt justified in
dropping the name injection.

To be truthful, I've never found a case before where it made
a difference. In your case, for example, there's no problem
declaring the name before (or after) the definition of the
class. The difference really only comes into play for friends
in templates, e.g.:

template<typename T>
class C
{
// ...
friend std::eek:stream operator<<(
std::eek:stream& dest,
C const& obj)
{
// ...
}
};

Note that in this case, the operator<< function is *not*
a template. If it were not defined inline, in the class
template, you'd have to provide a separate, non-template version
for each instantiation of class C. Which sort of defeats the
purpose of making C a template. In early C++, each operator<<
was visible outside the class template, because of friend name
injection. In modern C++, it's found by ADL, so name injection
isn't necessary.
 
M

moogyd

Hi,

Thanks Victor and James for the replies.

As a bit of background, there are a couple C++ projects I have come
across that require the -ffriend_injection option to compile. Both
these (SystemC and Teal/Truss) are targeted at C++ in hardware design
and/or verification.
I was therefore trying to understand what this meant in real terms.

It seems that I need a deeper understanding of C++ (e.g. "ADL") before
I fully understand the issues.

Steven
 
B

Bart van Ingen Schenau

It seems that I need a deeper understanding of C++ (e.g. "ADL") before
I fully understand the issues.

ADL stands for "Argument Dependent Lookup" and essentially means that
the arguments for a function or operator can nominate additional
scopes (mostly namespaces) to search for overloads of the function/
operator.

Bart v Ingen Schenau
 
J

James Kanze

ADL stands for "Argument Dependent Lookup" and essentially
means that the arguments for a function or operator can
nominate additional scopes (mostly namespaces) to search for
overloads of the function/ operator.

Mostly namespaces, but in the case that interests us in
particular here, classes. (IIRC, classes were added to ADT
expressedly to cover the cases where friend name injection was
used before.)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top