nonmember functions?

Discussion in 'C++' started by desktop, May 23, 2007.

  1. desktop

    desktop Guest

    I have read that the allocator class has the following nonmember functions:

    template <class In, class For> For uninitialized_copy(In,In,For);
    template <class For, class T>
    void uninitialized_fill(For, For, const T&);

    But what does it mean that the two functions are nonmembers? Are they
    defined outside the class declaration in the header file?
     
    desktop, May 23, 2007
    #1
    1. Advertising

  2. desktop

    Fei Liu Guest

    desktop wrote:
    > I have read that the allocator class has the following nonmember functions:
    >
    > template <class In, class For> For uninitialized_copy(In,In,For);
    > template <class For, class T>
    > void uninitialized_fill(For, For, const T&);
    >
    > But what does it mean that the two functions are nonmembers? Are they
    > defined outside the class declaration in the header file?


    It means the 2 functions are not members of the allocator class. They
    could be declared as friend functions of the allocator class. As to
    definition, they can be either inside or outside of the class declaration.

    F
     
    Fei Liu, May 23, 2007
    #2
    1. Advertising

  3. desktop

    Howard Guest

    "Fei Liu" <> wrote in message
    news:f326s4$j0b$...
    > desktop wrote:
    >> I have read that the allocator class has the following nonmember
    >> functions:
    >>
    >> template <class In, class For> For uninitialized_copy(In,In,For);
    >> template <class For, class T>
    >> void uninitialized_fill(For, For, const T&);
    >>
    >> But what does it mean that the two functions are nonmembers? Are they
    >> defined outside the class declaration in the header file?

    >
    > It means the 2 functions are not members of the allocator class. They
    > could be declared as friend functions of the allocator class.


    They could be. They don't have to be. If the class has no private or
    protected members which the functions need access to, then there's no need
    to write friend declarations for them in the allocator class.

    > As to definition, they can be either inside or outside of the class
    > declaration.
    >


    Eh? How can you define a non-member function *inside* the class? Simply
    declaring it inside the class (let alone defining it), makes it a member
    function. (Unless, of course, you're talking about a friend declaration.
    But that's still just a friend declaration, not a function definition.)

    -Howard
     
    Howard, May 23, 2007
    #3
  4. desktop

    Marcus Kwok Guest

    Howard <> wrote:
    > Eh? How can you define a non-member function *inside* the class? Simply
    > declaring it inside the class (let alone defining it), makes it a member
    > function. (Unless, of course, you're talking about a friend declaration.
    > But that's still just a friend declaration, not a function definition.)


    Like this:

    #include <iostream>

    class Foo {
    public:
    Foo() : i_(42) { }

    friend void print(const Foo& f)
    {
    std::cout << f.i_ << '\n';
    }

    private:
    int i_;
    };

    int main()
    {
    Foo f;
    print(f);
    //f.print();
    }


    Uncomment f.print() to get a compilation error saying that print() is
    not a member of Foo, but print() is defined inside the class.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, May 23, 2007
    #4
  5. desktop

    Pete Becker Guest

    desktop wrote:
    > I have read that the allocator class has the following nonmember functions:
    >
    > template <class In, class For> For uninitialized_copy(In,In,For);
    > template <class For, class T>
    > void uninitialized_fill(For, For, const T&);
    >
    > But what does it mean that the two functions are nonmembers? Are they
    > defined outside the class declaration in the header file?


    It's a bit misleading. They're non-member functions in the sense that
    they aren't member functions of any class. But they have no special
    relationship to allocators. They're general purpose algorithms that
    happen to be useful for allocators among other things.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, May 23, 2007
    #5
  6. desktop

    Howard Guest

    "Marcus Kwok" <> wrote in message
    news:f32bip$703$...
    > Howard <> wrote:
    >> Eh? How can you define a non-member function *inside* the class? Simply
    >> declaring it inside the class (let alone defining it), makes it a member
    >> function. (Unless, of course, you're talking about a friend declaration.
    >> But that's still just a friend declaration, not a function definition.)

    >
    > Like this:
    >
    > #include <iostream>
    >
    > class Foo {
    > public:
    > Foo() : i_(42) { }
    >
    > friend void print(const Foo& f)
    > {
    > std::cout << f.i_ << '\n';
    > }
    >
    > private:
    > int i_;
    > };
    >
    > int main()
    > {
    > Foo f;
    > print(f);
    > //f.print();
    > }
    >
    >
    > Uncomment f.print() to get a compilation error saying that print() is
    > not a member of Foo, but print() is defined inside the class.
    >


    Interesting. Can't say as I've ever seen a friend function actually
    *defined* inside a class. Is it portable? (It looks like this may be
    related to a recent discussion about "injecting" a function into a namespace
    via a friend declaration.) How is it affected by the visibility within that
    class? Would it have to be in the a public section to be seen from outside,
    even though it's not a member? Can it be specified via
    Foo::print(whatever), or is it just a member of the enclosing namespace?

    -Howard
     
    Howard, May 23, 2007
    #6
  7. desktop

    Marcus Kwok Guest

    Howard <> wrote:
    > "Marcus Kwok" <> wrote in message
    > news:f32bip$703$...
    >> Howard <> wrote:
    >>> Eh? How can you define a non-member function *inside* the class? Simply
    >>> declaring it inside the class (let alone defining it), makes it a member
    >>> function. (Unless, of course, you're talking about a friend declaration.
    >>> But that's still just a friend declaration, not a function definition.)

    >>
    >> Like this:
    >>
    >> #include <iostream>
    >>
    >> class Foo {
    >> public:
    >> Foo() : i_(42) { }
    >>
    >> friend void print(const Foo& f)
    >> {
    >> std::cout << f.i_ << '\n';
    >> }
    >>
    >> private:
    >> int i_;
    >> };
    >>
    >> int main()
    >> {
    >> Foo f;
    >> print(f);
    >> //f.print();
    >> }

    >
    > Interesting. Can't say as I've ever seen a friend function actually
    > *defined* inside a class. Is it portable? (It looks like this may be
    > related to a recent discussion about "injecting" a function into a namespace
    > via a friend declaration.)


    I can't say with 100% certainty, but I think it is. I first saw this
    technique in a post here a while ago, but with a friend operator<<, and
    nobody called him out on it.

    > How is it affected by the visibility within that
    > class? Would it have to be in the a public section to be seen from outside,
    > even though it's not a member?


    I tried putting it in the private section and it still worked.

    > Can it be specified via
    > Foo::print(whatever), or is it just a member of the enclosing namespace?


    I tried using it as Foo::print() and I got a compilation error saying
    that print() is not a member of Foo, which makes sense since it is not a
    class static function. Therefore, I would say that it is just a member
    of the enclosing namespace.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, May 24, 2007
    #7
  8. desktop

    James Kanze Guest

    On May 23, 11:55 pm, "Howard" <> wrote:
    > "Marcus Kwok" <> wrote in message
    > news:f32bip$703$...
    > > Howard <> wrote:
    > >> Eh? How can you define a non-member function *inside* the class? Simply
    > >> declaring it inside the class (let alone defining it), makes it a member
    > >> function. (Unless, of course, you're talking about a friend declaration.
    > >> But that's still just a friend declaration, not a function definition.)


    > > Like this:


    > > #include <iostream>


    > > class Foo {
    > > public:
    > > Foo() : i_(42) { }


    > > friend void print(const Foo& f)
    > > {
    > > std::cout << f.i_ << '\n';
    > > }


    > > private:
    > > int i_;
    > > };


    > > int main()
    > > {
    > > Foo f;
    > > print(f);
    > > //f.print();
    > > }


    > > Uncomment f.print() to get a compilation error saying that print() is
    > > not a member of Foo, but print() is defined inside the class.


    > Interesting. Can't say as I've ever seen a friend function actually
    > *defined* inside a class. Is it portable?


    [I thought I'd already answered this, but I don't see my
    posting...]

    It's a fairly well known idiom, first published, I think, by
    Barton and Nackman. The committee took it into consideration
    when changing the rules for name lookup; even then, breaking it
    was considered to be something that would break too much code.

    > (It looks like this may be
    > related to a recent discussion about "injecting" a function into a namespace
    > via a friend declaration.)


    Yup. Historically, it worked because friend names were injected
    into the surrounding namespace scope (or file scope, given that
    namespaces didn't exist). This injection caused problems
    elsewhere (I forget what), and the committee did away with it.
    But only because ADL could now be used to find the name.

    Note that there are special cases which were broken. Consider
    the following:

    class A {} ;

    class B
    {
    public:
    B( A const& ) {}
    friend void print( B const& ) {}
    } ;

    int main()
    {
    A anA ;
    print( anA ) ;
    return 0 ;
    }

    According to the old (pre-1998) rules, this is legal; print is
    injected into the global namespace, name lookup in main finds
    it, and overload resolution uses the convertion constructor to
    convert the argument and call it. Under the new rules, there is
    nothing in the arguments which relates to B, so the compiler
    does not look there in ADL, and so the code fails to compile.

    Many compilers (VC++ 8, Sun CC 5.8, g++ pre-4.0) still implement
    friend injection; of the compilers I have access to, the only
    one which complains about this code is g++ 4.1.0.

    > How is it affected by the visibility within that
    > class?


    I think you mean access control. Visibility is a rather vague
    term, related to name look up, and everything in a class
    definition has the same "visibility". Access control (public,
    private, etc.) only affects members, and a friend is not a
    member.

    > Would it have to be in the a public section to be seen from outside,
    > even though it's not a member?


    No.

    Think about it for a minute. I can also declare the friend
    outside of the class. Should it be accessible then, but not if
    I don't.

    A friend is not a member. Given something like:

    namespace A {
    class B {
    friend void f() ;
    } ;
    }

    The function declared by the friend declaration is A::f(), not
    A::B::f(). Regardless of where it is defined. "Visibility"
    (i.e. whether name lookup will find the symbol or not),
    membership and access control or largely orthogonal issues. In
    the example immediately above, f() is a member of A, and it's
    fully qualified name is A::f(). It is, however, only visible in
    contexts where name lookup looks into B: in member functions of
    B, or when ADL kicks in for B. (Theoretically, it's also
    visible in contexts like "someB.f()", after the dot. But in
    those contexts, only members are considered, and since it's not
    a member...)

    Access control only affects members, and it is only applied
    after name lookup and overload resolution have taken place; if
    overload resolution chooses a private function, it's an error,
    even if there is a public function of the same name which could
    be called.

    > Can it be specified via
    > Foo::print(whatever), or is it just a member of the enclosing namespace?


    It's just a member of the enclosing namespace. Even though it
    isn't visible there:).

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, May 25, 2007
    #8
  9. On 25 May 2007 00:05:16 -0700, James Kanze wrote:

    >Note that there are special cases which were broken. Consider
    >the following:
    >
    > class A {} ;
    >
    > class B
    > {
    > public:
    > B( A const& ) {}
    > friend void print( B const& ) {}
    > } ;
    >
    > int main()
    > {
    > A anA ;
    > print( anA ) ;
    > return 0 ;
    > }
    >
    >According to the old (pre-1998) rules, this is legal; print is
    >injected into the global namespace, name lookup in main finds
    >it, and overload resolution uses the convertion constructor to
    >convert the argument and call it. Under the new rules, there is
    >nothing in the arguments which relates to B, so the compiler
    >does not look there in ADL, and so the code fails to compile.
    >
    >Many compilers (VC++ 8, Sun CC 5.8, g++ pre-4.0) still implement
    >friend injection; of the compilers I have access to, the only
    >one which complains about this code is g++ 4.1.0.


    And in the serious, responsible, tradition of g++ there's a temporary
    option, -ffriend-injection, which can help in the transition:

    <http://gcc.gnu.org/gcc-4.1/changes.html>

    --
    Gennaro Prota -- C++ Developer, For Hire
    https://sourceforge.net/projects/breeze/
    (please check 'Status <date>' link in Summary page)
     
    Gennaro Prota, May 25, 2007
    #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. Erik Haugen

    nonmember vs member?

    Erik Haugen, Oct 24, 2003, in forum: C++
    Replies:
    13
    Views:
    627
    jeffc
    Oct 24, 2003
  2. Xiangliang Meng
    Replies:
    1
    Views:
    1,608
    Victor Bazarov
    Jun 21, 2004
  3. Replies:
    1
    Views:
    274
    Victor Bazarov
    Jul 29, 2005
  4. nonmember function

    , Aug 1, 2005, in forum: C++
    Replies:
    3
    Views:
    294
    msalters
    Aug 3, 2005
  5. Replies:
    2
    Views:
    271
Loading...

Share This Page