By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,030 Members | 1,015 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,030 IT Pros & Developers. It's quick & easy.

ISO/IEC 14882 3.3 friend, extern and scope

P: n/a
This note appears in the discussion of name hiding and uniqueness:

3.3 #4[Note: these restrictions apply to the declarative region into which
a name is introduced, which is not necessarily the same as the region in
which the declaration occurs. In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace; these restrictions apply to that
region. Local extern declarations (3.5) may introduce a name into the
declarative region where the declaration appears and also introduce a
(possibly not visible) name into an enclosing namespace; these restrictions
apply to both regions.]

This note is item #6 in the discussion of "Point of declaration"
3.3.1 #6[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace, but they do not introduce new
names into that namespace (7.3.1.2). Function declarations at block scope
and object declarations with the extern specifier at block scope refer to
declarations that are members of an enclosing namespace, but they do not
introduce new names into that scope. ]

What exactly do these statements mean?

"[E]laborated-type-specifiers and friend declarations may introduce a
(possibly not visible) name into an enclosing namespace;"

"Local extern declarations may introduce a name into the declarative region
where the declaration appears and also introduce a (possibly not visible)
name into an enclosing namespace;"

"Friend declarations refer to functions or classes that are members of the
nearest enclosing namespace, but they do not introduce new names into that
namespace"

"[O]bject declarations with the extern specifier at block scope refer to
declarations that are members of an enclosing namespace, but they do not
introduce new names into that scope."

Not only do I not understand their basic meaning, they seem contradictory to
me. The part about "elaborated-type-specifiers" I take to mean "forward
declarations", and the statement appears to mean that bar is introduced
into the namespace foo in this example:

namespace foo{ class bar; }

But what is it saying the friend declaration is introducing into the
namespace foo in this example?

namespace foo{ struct bar{ friend void baz(int i); }; }

The same goes for extern?

--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/
Dec 7 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Steven T. Hatton wrote:
This note appears in the discussion of name hiding and uniqueness:
....
This note is item #6 in the discussion of "Point of declaration"
3.3.1 #6[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace, but they do not introduce new
names into that namespace (7.3.1.2). Function declarations at block scope
and object declarations with the extern specifier at block scope refer to
declarations that are members of an enclosing namespace, but they do not
introduce new names into that scope. ]

What exactly do these statements mean?
struct A
{
friend struct B;
};

B * b;

The code above is not valid.

So the friend declaration for B does not introduce a struct B but it
does point to it. This means that the code above is invalid.
struct A
{
friend struct B;
};

struct B;
B * b;

This code is now valid.

The same goes for extern?
No.
Dec 8 '06 #2

P: n/a
Gianni Mariani wrote:
Steven T. Hatton wrote:
>This note appears in the discussion of name hiding and uniqueness:
...
>This note is item #6 in the discussion of "Point of declaration"
3.3.1 #6[Note: friend declarations refer to functions or classes that
are members of the nearest enclosing namespace, but they do not introduce
new names into that namespace (7.3.1.2). Function declarations at block
scope and object declarations with the extern specifier at block scope
refer to declarations that are members of an enclosing namespace, but
they do not introduce new names into that scope. ]

What exactly do these statements mean?

struct A
{
friend struct B;
};

B * b;

The code above is not valid.

So the friend declaration for B does not introduce a struct B but it
does point to it. This means that the code above is invalid.
struct A
{
friend struct B;
};

struct B;
B * b;

This code is now valid.
I get it. If the declaration of B were a definition - which could never be
the case for an object such as B - then that definition would introduce B
into the enclosing namespace. Right?
>
>The same goes for extern?

No.
--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/
Dec 8 '06 #3

P: n/a
Steven T. Hatton wrote:
....
>
I get it. If the declaration of B were a definition - which could never be
the case for an object such as B - then that definition would introduce B
into the enclosing namespace. Right?
I think your terminology of definition and declaration is wrong.

struct B; // declaration

struct B {}; // definition

friend struct B; // "friend declaration"
If we use the teminology from the standard:

"friend struct B" does not "introduce" "struct B" into the namespace.

"struct B" does introduce itself into the namespace, however, that
exactly what it's purpose is so you would expect it to.
Dec 8 '06 #4

P: n/a
Gianni Mariani wrote:
Steven T. Hatton wrote:
...
>>
I get it. If the declaration of B were a definition - which could never
be the case for an object such as B - then that definition would
introduce B
into the enclosing namespace. Right?

I think your terminology of definition and declaration is wrong.
I should have said "object type" such as B.
#include <iostream>
namespace foo {

struct Bar {
Bar():_splat("SPLAT!"){}
friend const char* A(const Bar& b);
friend const char* B(const Bar& b)
{ return b._splat; }//B is defined, but B is not an object type.
private:
const char* _splat;
};

//Is A here, yet "possibly not visible"?

void baz () {
Bar bar;
std::cout<<B(bar)<<std::endl;
//B is visible in the enclosing Bar's enclosing scope.
}

}

int main(){
foo::baz();
}
struct B; // declaration

struct B {}; // definition

friend struct B; // "friend declaration"
If we use the teminology from the standard:

"friend struct B" does not "introduce" "struct B" into the namespace.
Does it? 3.3/4 "friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;"

I am pretty sure that is an error in the Standard. I cannot reconcile it
with the following unless I allow that the declaration may also be a
definition:

3.3 "Every name is introduced in some portion of program text called a
declarative region, which is the largest part of the program in which that
name is valid, that is, in which that name may be used as an unqualified
name to refer to the same entity. In general, each particular name is valid
only within some possibly discontiguous portion of program text called its
scope."

3.3.7/5 "If a name is in scope and is not hidden it is said to be visible."

If I do allow that a declaration may also be a definition, then the
following appears to be in error:

3.3.1 #6"friend declarations refer to functions or classes that are members
of the nearest enclosing namespace, but they do not introduce new
names into that namespace."

To be honest, the more closely I read clause 3, the more I realize that it
contains several subtle errors.
--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/
Dec 14 '06 #5

P: n/a
Steven T. Hatton wrote:
Gianni Mariani wrote:
>Steven T. Hatton wrote:
...
>>>
I get it. If the declaration of B were a definition - which could never
be the case for an object such as B - then that definition would
introduce B
into the enclosing namespace. Right?

I think your terminology of definition and declaration is wrong.

I should have said "object type" such as B.
#include <iostream>
namespace foo {

struct Bar {
Bar():_splat("SPLAT!"){}
friend const char* A(const Bar& b);
friend const char* B(const Bar& b)
{ return b._splat; }//B is defined, but B is not an object type.
private:
const char* _splat;
};

//Is A here, yet "possibly not visible"?

void baz () {
Bar bar;
std::cout<<B(bar)<<std::endl;
//B is visible in the enclosing Bar's enclosing scope.
}

}

int main(){
foo::baz();
}
>struct B; // declaration

struct B {}; // definition

friend struct B; // "friend declaration"
If we use the teminology from the standard:

"friend struct B" does not "introduce" "struct B" into the namespace.

Does it? 3.3/4 "friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;"

I am pretty sure that is an error in the Standard. I cannot reconcile it
with the following unless I allow that the declaration may also be a
definition:

3.3 "Every name is introduced in some portion of program text called a
declarative region, which is the largest part of the program in which that
name is valid, that is, in which that name may be used as an unqualified
name to refer to the same entity. In general, each particular name is
valid only within some possibly discontiguous portion of program text
called its scope."

3.3.7/5 "If a name is in scope and is not hidden it is said to be
visible."

If I do allow that a declaration may also be a definition, then the
following appears to be in error:

3.3.1 #6"friend declarations refer to functions or classes that are
members of the nearest enclosing namespace, but they do not introduce new
names into that namespace."

To be honest, the more closely I read clause 3, the more I realize that it
contains several subtle errors.
Ha! I finally realized why everybody else is confused about my confusion.
I misunderstood the problem wrong! I still believe the wording in the
Standard is wrong, but now I believe it is wrong in more ways than I
thought. I wasn't expected to consider a definition to be a declaration
(even though it is). I was just supposed to be confused about the fact
that a name is both introduced and not introduced into a namespace at the
same time.

This make a who lot better nonsense than the other examples I posted:

#include <iostream>

namespace other {
struct D {
D():_data("D::_data"){}
const char* _data;
virtual void fun() const { std::cout<<"D::fun():"<<_data<<std::endl; }
};
void pal(const D& d){
std::cout<<"other::pal:"<<d._data<<std::endl;
d.fun();
}
}

namespace foo {
using other::D;
struct Bar: D {
Bar():_splat("SPLAT!"){}

friend void pal(const D& d);
friend const char* B(const Bar& b) { return b._splat; }
friend void chum(const Bar& b) { std::cout<<"chum
of "<<b._data<<std::endl; }

private:
const char* _splat;
virtual void fun() const { std::cout<<"Bar::fun():"<<_data<<std::endl; }

};
void baz () {
Bar* bar_ptr(new Bar);
std::cout<<B(*bar_ptr)<<std::endl;
other::pal(*bar_ptr);//Why do I need to qualify this?
chum(*bar_ptr);
delete bar_ptr;
}
}

int main(){
foo::baz();
}

--
NOUN:1. Money or property bequeathed to another by will. 2. Something handed
down from an ancestor or a predecessor or from the past: a legacy of
religious freedom. ETYMOLOGY: MidE legacie, office of a deputy, from OF,
from ML legatia, from L legare, to depute, bequeath. www.bartleby.com/61/
Dec 14 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.