Why can't forward declared friend class be referred in the class?
Clash Royale CLAN TAG#URR8PPP
up vote
23
down vote
favorite
The following code doesn't compile:
struct X
friend class Y;
Y* ptr;
;
The cppreference describes the situation as
... If the name of the class that is used in the friend declaration is
not yet declared, it is forward declared on the spot.
If the "spot" means where the friend relationship is declared, then it should be fine to declare the member Y* ptr
. Why doesn't it compile? Where in the standard prohibits this?
c++ friend
add a comment |Â
up vote
23
down vote
favorite
The following code doesn't compile:
struct X
friend class Y;
Y* ptr;
;
The cppreference describes the situation as
... If the name of the class that is used in the friend declaration is
not yet declared, it is forward declared on the spot.
If the "spot" means where the friend relationship is declared, then it should be fine to declare the member Y* ptr
. Why doesn't it compile? Where in the standard prohibits this?
c++ friend
3
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
1
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
2
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31
add a comment |Â
up vote
23
down vote
favorite
up vote
23
down vote
favorite
The following code doesn't compile:
struct X
friend class Y;
Y* ptr;
;
The cppreference describes the situation as
... If the name of the class that is used in the friend declaration is
not yet declared, it is forward declared on the spot.
If the "spot" means where the friend relationship is declared, then it should be fine to declare the member Y* ptr
. Why doesn't it compile? Where in the standard prohibits this?
c++ friend
The following code doesn't compile:
struct X
friend class Y;
Y* ptr;
;
The cppreference describes the situation as
... If the name of the class that is used in the friend declaration is
not yet declared, it is forward declared on the spot.
If the "spot" means where the friend relationship is declared, then it should be fine to declare the member Y* ptr
. Why doesn't it compile? Where in the standard prohibits this?
c++ friend
asked Aug 27 at 18:12
Kan Li
3,27833176
3,27833176
3
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
1
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
2
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31
add a comment |Â
3
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
1
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
2
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31
3
3
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
1
1
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
2
2
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
27
down vote
accepted
This is a mistake on the site. It contradicts the standard, which says that friendship declaration is not a substitute for a forward declaration:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
The part about the name not being visible to unqualified or qualified lookup essentially means that the name does not behave like a forward declaration.
So if you putclass Y;
before thefriend class Y;
at that point the classY
is declared and can then be used.
â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so theclass Y;
would need to be at whatever scope the class definition is located.
â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use thefriend
declaration to also declare a class. It will be better to delcare the class first before using thefriend
declaration.
â R Sahu
Aug 27 at 18:36
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
 |Â
show 1 more comment
up vote
2
down vote
In addition to the answer of @dasblinkenlight, a note in 3.3.2 Point of declaration lit. 10 explicitly says that a friend declaration does not introduce (and therefore not "forward declare") a class name:
10 [ 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 ([namespace.memdef]).
add a comment |Â
up vote
0
down vote
One way to fix this code is to simply add class
keyword:
struct X
friend class Y;
class Y* ptr;
;
This will forward declare class Y
at the global scope, if X
is in the global scope.
This will not "forward declare" anything, as it does not make it possible to use the nameY
alone like a real declaration would. This makesY
a member of the global scope only ifX
is also directly in the global scope. More generally, that code will twice use theY
which is associated with the innermost enclosing namespace or block scope.
â aschepler
Aug 28 at 3:50
@aschepler It was assumed thatX
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference betweenclass Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?
â Evg
Aug 28 at 7:24
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
27
down vote
accepted
This is a mistake on the site. It contradicts the standard, which says that friendship declaration is not a substitute for a forward declaration:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
The part about the name not being visible to unqualified or qualified lookup essentially means that the name does not behave like a forward declaration.
So if you putclass Y;
before thefriend class Y;
at that point the classY
is declared and can then be used.
â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so theclass Y;
would need to be at whatever scope the class definition is located.
â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use thefriend
declaration to also declare a class. It will be better to delcare the class first before using thefriend
declaration.
â R Sahu
Aug 27 at 18:36
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
 |Â
show 1 more comment
up vote
27
down vote
accepted
This is a mistake on the site. It contradicts the standard, which says that friendship declaration is not a substitute for a forward declaration:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
The part about the name not being visible to unqualified or qualified lookup essentially means that the name does not behave like a forward declaration.
So if you putclass Y;
before thefriend class Y;
at that point the classY
is declared and can then be used.
â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so theclass Y;
would need to be at whatever scope the class definition is located.
â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use thefriend
declaration to also declare a class. It will be better to delcare the class first before using thefriend
declaration.
â R Sahu
Aug 27 at 18:36
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
 |Â
show 1 more comment
up vote
27
down vote
accepted
up vote
27
down vote
accepted
This is a mistake on the site. It contradicts the standard, which says that friendship declaration is not a substitute for a forward declaration:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
The part about the name not being visible to unqualified or qualified lookup essentially means that the name does not behave like a forward declaration.
This is a mistake on the site. It contradicts the standard, which says that friendship declaration is not a substitute for a forward declaration:
7.3.1.2.3 Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
The part about the name not being visible to unqualified or qualified lookup essentially means that the name does not behave like a forward declaration.
answered Aug 27 at 18:29
dasblinkenlight
597k547411165
597k547411165
So if you putclass Y;
before thefriend class Y;
at that point the classY
is declared and can then be used.
â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so theclass Y;
would need to be at whatever scope the class definition is located.
â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use thefriend
declaration to also declare a class. It will be better to delcare the class first before using thefriend
declaration.
â R Sahu
Aug 27 at 18:36
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
 |Â
show 1 more comment
So if you putclass Y;
before thefriend class Y;
at that point the classY
is declared and can then be used.
â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so theclass Y;
would need to be at whatever scope the class definition is located.
â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use thefriend
declaration to also declare a class. It will be better to delcare the class first before using thefriend
declaration.
â R Sahu
Aug 27 at 18:36
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
So if you put
class Y;
before the friend class Y;
at that point the class Y
is declared and can then be used.â Richard Chambers
Aug 27 at 18:32
So if you put
class Y;
before the friend class Y;
at that point the class Y
is declared and can then be used.â Richard Chambers
Aug 27 at 18:32
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@RichardChambers but it would declare class Y that is local to X, not Y in the surrounding namespace.
â n.m.
Aug 27 at 18:33
@n.m. so the
class Y;
would need to be at whatever scope the class definition is located.â Richard Chambers
Aug 27 at 18:34
@n.m. so the
class Y;
would need to be at whatever scope the class definition is located.â Richard Chambers
Aug 27 at 18:34
@RichardChambers, yes. However, IMO, it's poor coding practice to use the
friend
declaration to also declare a class. It will be better to delcare the class first before using the friend
declaration.â R Sahu
Aug 27 at 18:36
@RichardChambers, yes. However, IMO, it's poor coding practice to use the
friend
declaration to also declare a class. It will be better to delcare the class first before using the friend
declaration.â R Sahu
Aug 27 at 18:36
4
4
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
I suspect what the quoted sentence is trying to say is that you don't need a forward declaration in order to declare a friend, it's implicitly forward-declared for that purpose.
â Barmar
Aug 27 at 20:41
 |Â
show 1 more comment
up vote
2
down vote
In addition to the answer of @dasblinkenlight, a note in 3.3.2 Point of declaration lit. 10 explicitly says that a friend declaration does not introduce (and therefore not "forward declare") a class name:
10 [ 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 ([namespace.memdef]).
add a comment |Â
up vote
2
down vote
In addition to the answer of @dasblinkenlight, a note in 3.3.2 Point of declaration lit. 10 explicitly says that a friend declaration does not introduce (and therefore not "forward declare") a class name:
10 [ 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 ([namespace.memdef]).
add a comment |Â
up vote
2
down vote
up vote
2
down vote
In addition to the answer of @dasblinkenlight, a note in 3.3.2 Point of declaration lit. 10 explicitly says that a friend declaration does not introduce (and therefore not "forward declare") a class name:
10 [ 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 ([namespace.memdef]).
In addition to the answer of @dasblinkenlight, a note in 3.3.2 Point of declaration lit. 10 explicitly says that a friend declaration does not introduce (and therefore not "forward declare") a class name:
10 [ 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 ([namespace.memdef]).
answered Aug 27 at 18:44
Stephan Lechner
21.9k21637
21.9k21637
add a comment |Â
add a comment |Â
up vote
0
down vote
One way to fix this code is to simply add class
keyword:
struct X
friend class Y;
class Y* ptr;
;
This will forward declare class Y
at the global scope, if X
is in the global scope.
This will not "forward declare" anything, as it does not make it possible to use the nameY
alone like a real declaration would. This makesY
a member of the global scope only ifX
is also directly in the global scope. More generally, that code will twice use theY
which is associated with the innermost enclosing namespace or block scope.
â aschepler
Aug 28 at 3:50
@aschepler It was assumed thatX
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference betweenclass Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?
â Evg
Aug 28 at 7:24
add a comment |Â
up vote
0
down vote
One way to fix this code is to simply add class
keyword:
struct X
friend class Y;
class Y* ptr;
;
This will forward declare class Y
at the global scope, if X
is in the global scope.
This will not "forward declare" anything, as it does not make it possible to use the nameY
alone like a real declaration would. This makesY
a member of the global scope only ifX
is also directly in the global scope. More generally, that code will twice use theY
which is associated with the innermost enclosing namespace or block scope.
â aschepler
Aug 28 at 3:50
@aschepler It was assumed thatX
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference betweenclass Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?
â Evg
Aug 28 at 7:24
add a comment |Â
up vote
0
down vote
up vote
0
down vote
One way to fix this code is to simply add class
keyword:
struct X
friend class Y;
class Y* ptr;
;
This will forward declare class Y
at the global scope, if X
is in the global scope.
One way to fix this code is to simply add class
keyword:
struct X
friend class Y;
class Y* ptr;
;
This will forward declare class Y
at the global scope, if X
is in the global scope.
edited Aug 28 at 7:09
answered Aug 27 at 19:36
Evg
2,2351130
2,2351130
This will not "forward declare" anything, as it does not make it possible to use the nameY
alone like a real declaration would. This makesY
a member of the global scope only ifX
is also directly in the global scope. More generally, that code will twice use theY
which is associated with the innermost enclosing namespace or block scope.
â aschepler
Aug 28 at 3:50
@aschepler It was assumed thatX
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference betweenclass Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?
â Evg
Aug 28 at 7:24
add a comment |Â
This will not "forward declare" anything, as it does not make it possible to use the nameY
alone like a real declaration would. This makesY
a member of the global scope only ifX
is also directly in the global scope. More generally, that code will twice use theY
which is associated with the innermost enclosing namespace or block scope.
â aschepler
Aug 28 at 3:50
@aschepler It was assumed thatX
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference betweenclass Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?
â Evg
Aug 28 at 7:24
This will not "forward declare" anything, as it does not make it possible to use the name
Y
alone like a real declaration would. This makes Y
a member of the global scope only if X
is also directly in the global scope. More generally, that code will twice use the Y
which is associated with the innermost enclosing namespace or block scope.â aschepler
Aug 28 at 3:50
This will not "forward declare" anything, as it does not make it possible to use the name
Y
alone like a real declaration would. This makes Y
a member of the global scope only if X
is also directly in the global scope. More generally, that code will twice use the Y
which is associated with the innermost enclosing namespace or block scope.â aschepler
Aug 28 at 3:50
@aschepler It was assumed that
X
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference between class Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?â Evg
Aug 28 at 7:24
@aschepler It was assumed that
X
was in the global scope, I refined my answer. Could you please explain your first sentence? What is the difference between class Y; struct X friend class Y; Y* ptr; ;
and the code in my answer?â Evg
Aug 28 at 7:24
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52044848%2fwhy-cant-forward-declared-friend-class-be-referred-in-the-class%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
3
@edtheprogrammerguy MSVC being able to compile something isn't the best of tests. both Clang and GCC fail to compile.
â NathanOliver
Aug 27 at 18:21
1
Please provide the specific compiler errors that you are seeing along with what compiler and version you are using.
â Richard Chambers
Aug 27 at 18:23
Ahh, that's not what "spot" means.
â Eljay
Aug 27 at 18:30
2
Minimal (non-)Compilable Verifiable Example with gcc and clang
â jaggedSpire
Aug 27 at 18:31