friend injection: Clarification Required

Discussion in 'C++' started by moogyd, Oct 20, 2010.

  1. moogyd

    moogyd Guest

    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
     
    moogyd, Oct 20, 2010
    #1
    1. Advertising

  2. On 10/20/2010 7:49 AM, moogyd wrote:
    > 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
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Oct 20, 2010
    #2
    1. Advertising

  3. moogyd

    James Kanze Guest

    On Oct 20, 12:49 pm, moogyd <> wrote:

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

    --
    James Kanze
     
    James Kanze, Oct 21, 2010
    #3
  4. moogyd

    moogyd Guest

    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
     
    moogyd, Oct 25, 2010
    #4
  5. On Oct 25, 11:35 am, moogyd <> wrote:
    >
    > 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.

    >
    > Steven


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Oct 26, 2010
    #5
  6. moogyd

    James Kanze Guest

    On Oct 26, 8:21 am, Bart van Ingen Schenau <>
    wrote:
    > On Oct 25, 11:35 am, moogyd <> wrote:


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


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

    --
    James Kanze
     
    James Kanze, Oct 26, 2010
    #6
    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. Replies:
    0
    Views:
    488
  2. CoolPint
    Replies:
    3
    Views:
    495
    Victor Bazarov
    Feb 13, 2005
  3. Replies:
    15
    Views:
    516
  4. somenath

    Clarification required for linkage.

    somenath, Feb 25, 2009, in forum: C Programming
    Replies:
    2
    Views:
    262
    somenath
    Feb 26, 2009
  5. Peter
    Replies:
    2
    Views:
    278
    Öö Tiib
    Jun 6, 2013
Loading...

Share This Page