Scope of a friend function defined inside a class definition + a doubt

Discussion in 'C++' started by Peter, Dec 17, 2010.

  1. Peter

    Peter Guest

    We all know what a friend function of a given class is: it's a
    function which is not a member of the class, but has an access to its
    non-public members. Usually we just declare a friend function inside a
    class definition and define it elsewhere (in global scope or as a
    member function of another class):

    class foo
    {
    friend void friendly_function(); // declaration without
    definition
    };

    void friendly_function() {some code} // definition in a global
    scope

    Defined this way, friendly_function() is visible anywhere from where
    it's defined to the end of file (unless overridden in some local scope
    by a variable with the same name).

    However, it's perfectly legal to place the DEFINITION of a friend
    function inside the definition of our class:

    class foo
    {
    friend void friendly_function() {some code} // definition inside a
    class definition
    };

    My questions are:

    1. What is the scope of friendly_function() now?

    2. What is the purpose of defining a friend function inside a
    definition of a class which befriends it? It seems quite confusing and
    illogical to me, my intuition tells me only a declaration should be
    allowed there. After all, why would anyone define a function which is
    NOT a member of a class inside that class? Since this is syntactically
    correct, there must be a reason for it, so please give me an example
    of situation where such a definition can be useful.


    Here comes my doubt. I have two, almost identical, snippets of code:

    #include <iostream>
    using namespace std;

    class foo
    {
    int x;
    friend void friendly_function(){} //empty DEFINITION
    };

    int main()
    {
    friendly_function();
    return 0;
    }

    which doesn't compile: g++ and Comeau give an error message about
    "friendly_function" identifier not being visible in main(), Visual C++
    seems to be more precise: " 'friendly_function': candidate function(s)
    not
    accessible could be the friend function at :
    'friendly_function' [may be found via
    argument-dependent lookup]".


    Interestingly though, the following fragment is compiled by all three:

    #include <iostream>
    using namespace std;

    class foo
    {
    int x;
    friend void friendly_function(foo&){} // empty
    DEFINITION, like before
    };

    int main()
    {
    foo obj;
    friendly_function(obj);
    return 0;
    }

    As you can see, the only difference is that previously
    friendly_function() took no arguments and now an object of foo class
    is passed to it by reference. Why does such a small change change the
    scope of friendly_function()? Previously it was inaccessible inside
    main() to all three compilers and now all three have access to it.
    Why?
     
    Peter, Dec 17, 2010
    #1
    1. Advertising

  2. Peter

    Balog Pal Guest

    "Peter" <>
    > However, it's perfectly legal to place the DEFINITION of a friend
    > function inside the definition of our class:
    >
    > class foo
    > {
    > friend void friendly_function() {some code} // definition inside a
    > class definition
    > };
    >
    > My questions are:
    >
    > 1. What is the scope of friendly_function() now?


    It's at "namespace scope" (IOW just outside the class), but not visible
    except through ADL. You can check its presense: declare an illegal overload
    (same params, different return type) and it will be rejected.

    > 2. What is the purpose of defining a friend function inside a
    > definition of a class which befriends it? It seems quite confusing and
    > illogical to me, my intuition tells me only a declaration should be
    > allowed there.


    The function you wrote does not make sense of course -- it has no params so
    ADL never finds it.
    This feature is used mostly for operators related to the class or something
    around. like operator << for streaming, binary operator +, and so on.
    Certainly you can have a set of overloaded free functions with a good name
    in a framework -- say serialize, some accessor shim, etc.

    >After all, why would anyone define a function which is
    > NOT a member of a class inside that class?


    google for why we want to define operator + as a nonbember rather than
    member.

    > Here comes my doubt. I have two, almost identical, snippets of code:


    Which are certainly far from identical...

    > #include <iostream>
    > using namespace std;
    >
    > class foo
    > {
    > int x;
    > friend void friendly_function(){} //empty DEFINITION
    > };
    >
    > int main()
    > {
    > friendly_function();
    > return 0;
    > }
    >
    > which doesn't compile: g++ and Comeau give an error message about
    > "friendly_function" identifier not being visible in main(),


    Well told.

    >Visual C++
    > seems to be more precise: " 'friendly_function': candidate function(s)
    > not
    > accessible could be the friend function at :
    > 'friendly_function' [may be found via
    > argument-dependent lookup]".


    An this one gives you all the possible hints. If you don't know what the
    message means look it up for more details. I'm sure pasting it in google
    provides a ton of explanation.

    > Interestingly though, the following fragment is compiled by all three:
    >
    > #include <iostream>
    > using namespace std;
    >
    > class foo
    > {
    > int x;
    > friend void friendly_function(foo&){} // empty
    > DEFINITION, like before
    > };
    >
    > int main()
    > {
    > foo obj;
    > friendly_function(obj);
    > return 0;
    > }
    >
    > As you can see, the only difference is that previously
    > friendly_function() took no arguments and now an object of foo class
    > is passed to it by reference. Why does such a small change change the
    > scope of friendly_function()?


    The first one is void, and the other has an argument of user defined type --
    so argument dependent lookup applies, and will add the related namespaces of
    all its arguments. finding the function where it is, in foo's namespace.
    (it would be conveniently found even if foo lived in some buried
    namespacewithout qualification.
     
    Balog Pal, Dec 17, 2010
    #2
    1. Advertising

  3. Re: Scope of a friend function defined inside a class definition+ a doubt

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    On 12/17/2010 02:17 PM, Peter wrote:
    > We all know what a friend function of a given class is: it's a
    > function which is not a member of the class, but has an access to its
    > non-public members. Usually we just declare a friend function inside a
    > class definition and define it elsewhere (in global scope or as a
    > member function of another class):
    >
    > class foo
    > {
    > friend void friendly_function(); // declaration without
    > definition
    > };
    >
    > void friendly_function() {some code} // definition in a global
    > scope
    >
    > Defined this way, friendly_function() is visible anywhere from where
    > it's defined to the end of file (unless overridden in some local scope
    > by a variable with the same name).
    >
    > However, it's perfectly legal to place the DEFINITION of a friend
    > function inside the definition of our class:
    >
    > class foo
    > {
    > friend void friendly_function() {some code} // definition inside a
    > class definition
    > };
    >
    > My questions are:
    >
    > 1. What is the scope of friendly_function() now?
    >
    > 2. What is the purpose of defining a friend function inside a
    > definition of a class which befriends it? It seems quite confusing and
    > illogical to me, my intuition tells me only a declaration should be
    > allowed there. After all, why would anyone define a function which is
    > NOT a member of a class inside that class? Since this is syntactically
    > correct, there must be a reason for it, so please give me an example
    > of situation where such a definition can be useful.
    >
    >
    > Here comes my doubt. I have two, almost identical, snippets of code:
    >
    > #include <iostream>
    > using namespace std;
    >
    > class foo
    > {
    > int x;
    > friend void friendly_function(){} //empty DEFINITION
    > };
    >
    > int main()
    > {
    > friendly_function();
    > return 0;
    > }
    >
    > which doesn't compile: g++ and Comeau give an error message about
    > "friendly_function" identifier not being visible in main(), Visual C++
    > seems to be more precise: " 'friendly_function': candidate function(s)
    > not
    > accessible could be the friend function at :
    > 'friendly_function' [may be found via
    > argument-dependent lookup]".
    >
    >
    > Interestingly though, the following fragment is compiled by all three:
    >
    > #include <iostream>
    > using namespace std;
    >
    > class foo
    > {
    > int x;
    > friend void friendly_function(foo&){} // empty
    > DEFINITION, like before
    > };
    >
    > int main()
    > {
    > foo obj;
    > friendly_function(obj);
    > return 0;
    > }
    >
    > As you can see, the only difference is that previously
    > friendly_function() took no arguments and now an object of foo class
    > is passed to it by reference. Why does such a small change change the
    > scope of friendly_function()? Previously it was inaccessible inside
    > main() to all three compilers and now all three have access to it.
    > Why?
    >
    >


    When a friend function is defined in a class, it is only in the scope of
    that class, not injected into the enclosing scope. In the second case,
    argument-dependent lookup is used, and the function is found. In the
    first case, there is no argument, so argument-dependent lookup can not
    be used.
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.16 (GNU/Linux)
    Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

    iQIcBAEBAgAGBQJNC+/uAAoJEO0SzzQOdchNCg0P/3SFdsDuMKTw0CRC+xKVQFty
    8YVzrnch4RG4zsmX5vzzSbLY0/ARaDDVQYpiBQMg7/di9wgTLxhPcyDS2hFc9+E7
    jB9bk41VA4VsOSxE0jOaYIbfm+p0JnamZGu5dBTYouvMiEZ3If38E0HZr+qtB8WA
    timjeliUPy5giTcNLrBUsX1LdfbtOaZ7b0ZUm3xvSoYt1l/pGG016xQTeKtqf8B0
    8SiE8apDKn1Y9asEiIk5JYCbJNl4JvXY206+cTDfxzBeOCl1a0vML5oWSUfgvE7Y
    yp54Kfk41h0mNaH6PqYjJDDhKww0BEXGYVNC/d1+Ap2/iLwS48JMM67jE2t1dSGp
    acC0O8t24/t9YHf2apcRlciF5nDaGDxLYVN6k41fAEI1k8KRDe++xA3cySHqBfuK
    X2TDTied+dUKgJGnZMrRIEtBVNtN2hOgWYBW8P54HCWGaiVW93YBagpVxnzGBORB
    Dr7Xe/r2ojr/6wzogc6TdW7iX9L8ZYLXxbE/Bki0SSKC1X4P/MRDMj0qCkT2bnPh
    6uYl2JvrIOQUlmUpD5o6NoRebnyOWYC/bAoQhGRALsYZVVRkYhDafEao3J8reqLu
    Yo6aTwJTFcD3Du4Xh8wAeojqzoYyHkmhrV6sfUiC0PfEYOOpDhLoEmFnnDB36Y8Y
    ebOIqK9oqthExeW7pV9X
    =zFHL
    -----END PGP SIGNATURE-----
     
    Garrett Hartshaw, Dec 17, 2010
    #3
  4. Peter

    Peter Guest

    > When a friend function is defined in a class, it is only in the scope of
    > that class, not injected into the enclosing scope. In the second case,
    > argument-dependent lookup is used, and the function is found. In the
    > first case, there is no argument, so argument-dependent lookup can not
    > be used.


    But if I change void friendly_function() to void
    friendly_function(int) my code still doesn't compile. Does the
    mechanism of argument-independent lookup require at least one of
    friendly_function's arguments to be of user-defined (class) type in
    order to work? Is this the only restriction? Last question: is ADL a
    standard feature of C++ or is it only a sort of extension offered by
    some compilers? Thanks for help, I promise to read about it before I
    write here again.
     
    Peter, Dec 18, 2010
    #4
  5. Re: Scope of a friend function defined inside a class definition+ a doubt

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    On 12/17/2010 07:02 PM, Peter wrote:
    >> When a friend function is defined in a class, it is only in the scope of
    >> that class, not injected into the enclosing scope. In the second case,
    >> argument-dependent lookup is used, and the function is found. In the
    >> first case, there is no argument, so argument-dependent lookup can not
    >> be used.

    >
    > But if I change void friendly_function() to void
    > friendly_function(int) my code still doesn't compile. Does the
    > mechanism of argument-independent lookup require at least one of
    > friendly_function's arguments to be of user-defined (class) type in
    > order to work? Is this the only restriction? Last question: is ADL a
    > standard feature of C++ or is it only a sort of extension offered by
    > some compilers? Thanks for help, I promise to read about it before I
    > write here again.
    >


    ADL is standard, and in order to find a friend function declared in a
    class through ADL, at least one of the arguments needs to be of (or a
    reference or pointer to) that class.
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.16 (GNU/Linux)
    Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

    iQIcBAEBAgAGBQJNDBAbAAoJEO0SzzQOdchN2MkP/0h6PgAuWwlArGHfnHbddIf1
    pgzRksb9gv5qzFiI+KwgEc2b4Sxd+sWGgSMpcpQv7s92TPgpXqkLPbkJXXW+Mt6Y
    z6ck4j9ICgbEwREMApKIuLipII2LiHBLWsuUmvbTJSqOHn9oRErsUFZUb5xrnp2d
    MaBkZS0SxMYQWsi2EDNnBCWDWo8HP9iNv6ZvszF/TMCL9AfRwupYdMhdgSJUelvB
    KH2Nh//aKI6JPxySwvYn6tnOFrA1Et1Z0G9zhKzWKQJ5sFzUiObSAsy3CDAdFHQb
    BgkJaX07lfqvvrHlgPh96Tl8vDfIED7sBKu6uFUSy4UPYrr6yjJuMxqHoBLpJpOR
    wns0JA1edne4rqUNMY5ZFdDHJGtKK2t9GE1vkbZqr0t26hcXgHUMpswQDHAqrYw/
    6FRB2/+/EnaAF6EjRQchWxiAJF+cJQWvQDt9rJoYN9X3YjI2bj8aor8V+GMJHua7
    t8n09wupc64t4VygC96DVgb/QiLeSOMVGP7eiA/Oz5hgYI29arla+DVePUL/mXHB
    ZQoFlx7mCTCwVbo3WaSaBoMW7W7vz20PM+pr/ZEVpx7jREDsA04K5/jqVE8rXRBL
    DV2kyCto6ORAWG2i5XayWfVsGSBTyqoxH7T51cjcwyNBppvM67JpG3V77Rd7hpXA
    maolTFxqqPtzrAV5T7b5
    =oBwT
    -----END PGP SIGNATURE-----
     
    Garrett Hartshaw, Dec 18, 2010
    #5
  6. Peter

    Peter Guest

    > mechanism of argument-independent lookup

    Oops, I meant "dependent".
     
    Peter, Dec 18, 2010
    #6
  7. Peter

    James Kanze Guest

    On Dec 17, 7:17 pm, Peter <> wrote:
    > We all know what a friend function of a given class is: it's a
    > function which is not a member of the class, but has an access to its
    > non-public members. Usually we just declare a friend function inside a
    > class definition and define it elsewhere (in global scope or as a
    > member function of another class):


    I'd argue with your "usually". In my code, a friend function is
    usually defined inline in the class. It's fairly rare for there
    to be a definition (or an additional declaration) elsewhere.

    In almost all other cases, there will be a declaration *before*
    the class definition.

    > class foo
    > {
    > friend void friendly_function(); // declaration without definition
    > };


    > void friendly_function() {some code} // definition in a global scope


    > Defined this way, friendly_function() is visible anywhere from where
    > it's defined to the end of file (unless overridden in some local scope
    > by a variable with the same name).


    > However, it's perfectly legal to place the DEFINITION of a friend
    > function inside the definition of our class:


    > class foo
    > {
    > friend void friendly_function() {some code} // definition inside a class definition
    > };


    > My questions are:


    > 1. What is the scope of friendly_function() now?


    The scope is the nearest enclosing namespace, just as in the
    previous case. The visibility, however, is only within the
    class; the compiler will only see the function in cases where it
    looks inside the class, either because it is in class scope
    (member function, etc.), or because ADL causes it to look inside
    the class.

    > 2. What is the purpose of defining a friend function inside a
    > definition of a class which befriends it? It seems quite confusing and
    > illogical to me, my intuition tells me only a declaration should be
    > allowed there. After all, why would anyone define a function which is
    > NOT a member of a class inside that class?


    Why would anyone define any function inside a class?

    In practice, it's usually used in templates (and the purpose of
    friend is often just to allow defining a free function inside a
    class---the function doesn't actually access any class members,
    and in one frequent idiom, the class doesn't even have any
    members). The problem is simple:

    template<typename T>
    class Toto
    {
    friend void f(Toto const& obj);
    };

    This declares a friend function f. The friend is a *function*,
    not a template! So you have to define a (non-template) f for
    every instantiation of the template. If, on the other hand, you
    write:

    template<typename T>
    class Toto
    {
    friend void f(Toto const& obj)
    {
    // implementation...
    }
    };

    The compiler will generate the implementation of f every time it
    is used, for the class it is used with.

    And, of course, ADL will cause the compiler to look inside the
    class for such functions whenever the function is used. (Maybe.
    ADL triggers on the types of the arguments, not the types that
    might result from a conversion. So if Toto<T> has a converting
    constructor Toto::Toto(T const&), and you call f with something
    other than Toto<T>, the compiler will not look inside Toto<T>,
    and will not find the function.)

    This is most frequently used for operators, rather than named
    functions. How do you declare and implement std::eek:stream
    operator<<(std::eek:stream&, Toto<T> const&) otherwise. (Of
    course, you could make it a template as well, and make the
    template instantiation a friend. But using an inline
    instantiation of a friend is easier and less verbose.)

    There are many common idioms where non-member operators are
    implemented using member operators, e.g. operator+ is a free
    function implemented in terms of the member operator+=. In such
    cases, it is usual to use some generic base class, along the
    lines of:

    template<typename T>
    struct ArithmeticOperators
    {
    friend T operator+(T const& lhs, T const& rhs)
    {
    T result(lhs);
    result += rhs;
    return result;
    }
    // and so on, for all of the arithmetic operators.
    };

    The numeric class then inherits from this class, e.g.:

    class NumericType : public ArithmeticOperators<NumericType>
    {
    public:
    NumericType& operator+=(NumericType const& other);
    // ...
    };

    and automatically gets the non-assignment binary operator for every
    assignment operator it defines. (Note that the reason for
    friend here is *only* to be able to define the class in the
    function body. ArithmeticOperators has no members for the
    friend's to access.)

    I use this in a number of cases: ArithmeticOperators (for all of
    the binary arithmetic and logical operators), Comparison
    operators (==, <, etc. which forward to isEqual or compare, with
    simple meta programming to use isEqual for == and !=, if it
    exists, and otherwise compare), and IOOperators (<< and >>,
    which forward to print and scan---less useful than the others,
    unless print and scan are virtual).

    --
    James Kanze
     
    James Kanze, Dec 18, 2010
    #7
  8. Peter

    ptyxs Guest

    Peter wrote :

    > Since this is syntactically correct, there must be a reason for it,


    I wonder whether it is right to assert that the reason for a given
    construct to be legal is always (in C++ or widely in any language)
    that the construct is useful or usable. Perhaps the reason may be, in
    some cases (not necessarily in the present case), some internal
    constraint of the language.
    What do you think ?
     
    ptyxs, Dec 19, 2010
    #8
  9. Peter

    James Kanze Guest

    On Dec 19, 10:36 am, ptyxs <> wrote:
    > Peter wrote :


    > > Since this is syntactically correct, there must be a reason for it,


    > I wonder whether it is right to assert that the reason for a given
    > construct to be legal is always (in C++ or widely in any language)
    > that the construct is useful or usable. Perhaps the reason may be, in
    > some cases (not necessarily in the present case), some internal
    > constraint of the language.
    > What do you think ?


    There are many different reasons why the committee might make
    some particular construct legal. Perhaps the most general is
    that they simply didn't see any reason to forbid it; the overall
    philosophy is when in doubt, to allow something, rather than
    forbid it. And there are certainly things you can do which
    generally aren't very useful (but maybe someone will invent
    a use for them in the future).

    This is definitely not the case here: the construct is part of
    a standard idiom, and when changes elsewhere threatended to make
    it illegal, the committee actually made the necessary
    modifications so that it remained legal.

    --
    James Kanze
     
    James Kanze, Dec 20, 2010
    #9
    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. Jianli Shen
    Replies:
    1
    Views:
    637
    Victor Bazarov
    Mar 13, 2005
  2. Ark
    Replies:
    1
    Views:
    450
    Chris Torek
    Aug 7, 2004
  3. Replies:
    1
    Views:
    2,750
    =?ISO-8859-1?Q?Stefan_N=E4we?=
    Jan 9, 2006
  4. Mike
    Replies:
    1
    Views:
    437
    Juha Nieminen
    Jan 16, 2011
  5. Mike
    Replies:
    6
    Views:
    791
Loading...

Share This Page