nonmember functions?

D

desktop

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?
 
F

Fei Liu

desktop said:
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
 
H

Howard

Fei Liu said:
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
 
M

Marcus Kwok

Howard said:
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.
 
P

Pete Becker

desktop said:
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)
 
H

Howard

Marcus Kwok said:
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
 
M

Marcus Kwok

Howard said:
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.
 
J

James Kanze

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

Gennaro Prota

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>
 

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,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top