Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nonmember functions?

14 views
Skip to first unread message

desktop

unread,
May 23, 2007, 3:57:46 PM5/23/07
to
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?

Fei Liu

unread,
May 23, 2007, 4:06:51 PM5/23/07
to

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

Howard

unread,
May 23, 2007, 5:19:28 PM5/23/07
to

"Fei Liu" <fei...@aepnetworks.com> wrote in message
news:f326s4$j0b$1...@aioe.org...

> 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


Marcus Kwok

unread,
May 23, 2007, 5:26:50 PM5/23/07
to
Howard <ali...@hotmail.com> 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

Pete Becker

unread,
May 23, 2007, 5:33:03 PM5/23/07
to

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)

Howard

unread,
May 23, 2007, 5:55:14 PM5/23/07
to

"Marcus Kwok" <rice...@gehennom.invalid> wrote in message
news:f32bip$703$1...@news-int2.gatech.edu...

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


Marcus Kwok

unread,
May 24, 2007, 11:20:36 AM5/24/07
to
Howard <ali...@hotmail.com> wrote:
> "Marcus Kwok" <rice...@gehennom.invalid> wrote in message
> news:f32bip$703$1...@news-int2.gatech.edu...
>> Howard <ali...@hotmail.com> 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.

James Kanze

unread,
May 25, 2007, 3:05:16 AM5/25/07
to
On May 23, 11:55 pm, "Howard" <alic...@hotmail.com> wrote:
> "Marcus Kwok" <ricec...@gehennom.invalid> wrote in message
> news:f32bip$703$1...@news-int2.gatech.edu...

> > Howard <alic...@hotmail.com> 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:james...@gmail.com
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

Gennaro Prota

unread,
May 25, 2007, 12:59:19 PM5/25/07
to
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)

0 new messages