473,403 Members | 2,071 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,403 software developers and data experts.

Function declared before call but defined after - compilation fails

Hello All,

I am doing another exercise (I repeat, *exercise*). The (irrelevant to
this
discussion) point is to show that "You can inject a friend declaration
into
a namespace by declaring it within an enclosed class". I have done
this
successfully, but please consider the following program:

//: C10:FriendInjection.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
namespace Me {
class Us {
//...
public:
friend void you();
};
}
// 1
void Me::you(){}

int main() {
Me::you();
return 0;
}

// 2
// defining you() after main() does not compile
// void Me::you(){}
///:~
/////////////////////////////////////////////////////////////////////////

If Me::you() is *defined* at (2) after the call in main(), gcc 4.1.1
says:
"error: 'you' is not a member of 'Me'". If, instead, Me::you is
*defined* at (1),
then it compiles.

MSVC++ Express compiles it either way without a problem, as expected.

Surely this is a bug in gcc?

May 16 '07 #1
11 2011

<jo**********@hotmail.comwrote in message
news:11*********************@q23g2000hsg.googlegro ups.com...
Hello All,

I am doing another exercise (I repeat, *exercise*). The (irrelevant to
this
discussion) point is to show that "You can inject a friend declaration
into
a namespace by declaring it within an enclosed class". I have done
this
successfully, but please consider the following program:

//: C10:FriendInjection.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
namespace Me {
class Us {
//...
public:
friend void you();
};
}
// 1
void Me::you(){}

int main() {
Me::you();
return 0;
}

// 2
// defining you() after main() does not compile
// void Me::you(){}
///:~
/////////////////////////////////////////////////////////////////////////

If Me::you() is *defined* at (2) after the call in main(), gcc 4.1.1
says:
"error: 'you' is not a member of 'Me'". If, instead, Me::you is
*defined* at (1),
then it compiles.

MSVC++ Express compiles it either way without a problem, as expected.

Surely this is a bug in gcc?
Why?

Declaring a function as a friend does not declare or define that function.
It merely states that said function is a friend.

In case (1), you're declaring *and* defining Me::you(). If you move that to
after main() as in case (2), then when main() is compiled, Me::you() has not
yet been declaredand so it's an error.

-Howard

May 16 '07 #2
JLS
On May 16, 11:38 am, johnbrown...@hotmail.com wrote:
Hello All,

I am doing another exercise (I repeat, *exercise*). The (irrelevant to
this
discussion) point is to show that "You can inject a friend declaration
into
a namespace by declaring it within an enclosed class". I have done
this
successfully, but please consider the following program:

//: C10:FriendInjection.cpp
// From Thinking in C++, 2nd Edition
// Available athttp://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
namespace Me {
class Us {
//...
public:
friend void you();
};}

// 1
void Me::you(){}

int main() {
Me::you();
return 0;

}

// 2
// defining you() after main() does not compile
// void Me::you(){}
///:~
/////////////////////////////////////////////////////////////////////////

If Me::you() is *defined* at (2) after the call in main(), gcc 4.1.1
says:
"error: 'you' is not a member of 'Me'". If, instead, Me::you is
*defined* at (1),
then it compiles.

MSVC++ Express compiles it either way without a problem, as expected.

Surely this is a bug in gcc?
What happens if you change it to

int main() {
Me::Us::you();
return 0;

I would have thought that the "Us" would be necessary.

May 16 '07 #3

"JLS" <de********@yahoo.comwrote in message
news:11**********************@n59g2000hsh.googlegr oups.com...
On May 16, 11:38 am, johnbrown...@hotmail.com wrote:
>Hello All,

I am doing another exercise (I repeat, *exercise*). The (irrelevant to
this
discussion) point is to show that "You can inject a friend declaration
into
a namespace by declaring it within an enclosed class". I have done
this
successfully, but please consider the following program:

//: C10:FriendInjection.cpp
// From Thinking in C++, 2nd Edition
// Available athttp://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
namespace Me {
class Us {
//...
public:
friend void you();
};}

// 1
void Me::you(){}

int main() {
Me::you();
return 0;

}

// 2
// defining you() after main() does not compile
// void Me::you(){}
///:~
/////////////////////////////////////////////////////////////////////////

If Me::you() is *defined* at (2) after the call in main(), gcc 4.1.1
says:
"error: 'you' is not a member of 'Me'". If, instead, Me::you is
*defined* at (1),
then it compiles.

MSVC++ Express compiles it either way without a problem, as expected.

Surely this is a bug in gcc?

What happens if you change it to

int main() {
Me::Us::you();
return 0;

I would have thought that the "Us" would be necessary.
Huh? The function you() is not a member of Us. It's a *friend* of Us.

-Howard

May 16 '07 #4
Surely this is a bug in gcc?

gcc 4.0.1 compiles it either way for me.

May 16 '07 #5
On May 16, 11:16 am, "Howard" <alic...@hotmail.comwrote:
<johnbrown...@hotmail.comwrote in message

Why?

Declaring a function as a friend does not declare or define that function.
It merely states that said function is a friend.

In case (1), you're declaring *and* defining Me::you(). If you move that to
after main() as in case (2), then when main() is compiled, Me::you() has not
yet been declared and so it's an error.

-Howard
Bruce Eckel has this to say in his book:

"Notice the two other friend functions. The first declares an ordinary
global function g( ) as a friend. But g( ) has not been previously
declared at the global scope! It turns out that friend can be used
this way to simultaneously declare the function *and* give it friend
status."

Of course, he could be wrong, but then again, so could you. I have not
read the standards myself, and I probably never will. Who agrees with
Bruce? With Howard?

May 16 '07 #6
On May 16, 5:38 pm, johnbrown...@hotmail.com wrote:
I am doing another exercise (I repeat, *exercise*). The
(irrelevant to this discussion) point is to show that "You can
inject a friend declaration into a namespace by declaring it
within an enclosed class".
This is not up to date. Originally, a name declared in a friend
declaration was injected into the enclosing namespace (or file
scope, as it was then). This was changed in the standard, and
friend names are no longer injected.
I have done this successfully, but
please consider the following program:
//: C10:FriendInjection.cpp
// From Thinking in C++, 2nd Edition
// Available athttp://www.BruceEckel.com
// (c) Bruce Eckel 2000
// Copyright notice in Copyright.txt
namespace Me {
class Us {
//...
public:
friend void you();
};}
// 1
void Me::you(){}
int main() {
Me::you();
return 0;

}
This should not compile with an up-to-date compiler. Bruce
Eckel doubtlessly learned C++ before the change:-).

This would be legal according to the ARM, if you dropped the
namespace. I suspect that there were also many compilers which
supported it when they first introduced namespace as well.
// 2
// defining you() after main() does not compile
// void Me::you(){}
///:~
/////////////////////////////////////////////////////////////////////////
If Me::you() is *defined* at (2) after the call in main(), gcc 4.1.1
says:
"error: 'you' is not a member of 'Me'". If, instead, Me::you is
*defined* at (1),
then it compiles.
MSVC++ Express compiles it either way without a problem, as expected.
Surely this is a bug in gcc?
I wouldn't call it a bug. Technically, g++ is correct,
according to the standard. MSV++ is correct, according to
pre-standard conventions.

In practice, it's hard to conceive of a real program where the
change makes a difference. The most typical use of the friend
function is for operator's, which have a parameter of the class
type, and in this case, ADL now picks up the name. (ADL wasn't
present in earlier C++.) FWIW: this change broke none of my
earlier C++ (although other changes did).

--
James Kanze (Gabi Software) email: ja*********@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

May 16 '07 #7
On May 16, 12:22 pm, BigBrian <w...@brianmielke.comwrote:
Surely this is a bug in gcc?

gcc 4.0.1 compiles it either way for me.
As does gcc-3.4.2, OpenWatcom 1.6 and DigitalMars 8.49. For what it's
worth, the Comeau compiler (with default options) at
http://www.comeaucomputing.com/tryitout/ likes neither (1) nor (2).

So Howard, does your compiler reject (2), as you say it should?

May 16 '07 #8

<jo**********@hotmail.comwrote in message
news:11**********************@n59g2000hsh.googlegr oups.com...
On May 16, 12:22 pm, BigBrian <w...@brianmielke.comwrote:
Surely this is a bug in gcc?

gcc 4.0.1 compiles it either way for me.

As does gcc-3.4.2, OpenWatcom 1.6 and DigitalMars 8.49. For what it's
worth, the Comeau compiler (with default options) at
http://www.comeaucomputing.com/tryitout/ likes neither (1) nor (2).

So Howard, does your compiler reject (2), as you say it should?
Nope. VC++ (from Visual Studio 2003) accepts it either way. But the
question is what does the standard say, not what does Microsoft (or any
other vendor) say. I don't have the standard handy (and I have a great deal
of trouble understanding its legalese style), but I think James Kanze's
answer covers it pretty well.

-Howard

May 16 '07 #9
On May 16, 3:39 pm, James Kanze <james.ka...@gmail.comwrote:
On May 16, 5:38 pm, johnbrown...@hotmail.com wrote:
I am doing another exercise (I repeat, *exercise*). The
(irrelevant to this discussion) point is to show that "You can
inject a friend declaration into a namespace by declaring it
within an enclosed class".

This is not up to date. Originally, a name declared in a friend
declaration was injected into the enclosing namespace (or file
scope, as it was then). This was changed in the standard, and
friend names are no longer injected.
I see. Well, the book is old ((c) 2000) and the compilers mentioned in
my later post are also old (mostly).
>
<cut>

I wouldn't call it a bug. Technically, g++ is correct,
according to the standard. MSV++ is correct, according to
pre-standard conventions.
<cut>
The most typical use of the friend
function is for operator's, which have a parameter of the class
type, and in this case, ADL now picks up the name. (ADL wasn't
present in earlier C++.)
Is this "ADL" why the mighty Comeau compiler accepts neither (1) nor
(2)?

May 17 '07 #10
On May 17, 4:35 am, johnbrown...@hotmail.com wrote:
On May 16, 3:39 pm, James Kanze <james.ka...@gmail.comwrote:
On May 16, 5:38 pm, johnbrown...@hotmail.com wrote:
I am doing another exercise (I repeat, *exercise*). The
(irrelevant to this discussion) point is to show that "You can
inject a friend declaration into a namespace by declaring it
within an enclosed class".
This is not up to date. Originally, a name declared in a friend
declaration was injected into the enclosing namespace (or file
scope, as it was then). This was changed in the standard, and
friend names are no longer injected.
I see. Well, the book is old ((c) 2000) and the compilers mentioned in
my later post are also old (mostly).
Exactly. In 2000, the standard was still very new, and most
compilers still implemented the pre-standard rules from the ARM.

I suspect that some compilers still implement them today, and
will continue to implement them, in order to avoid breaking
existing code. The vendors of other compilers may decide that
the amount of code actually involved is small enough to not be
worth the bother---as I said, if the function has parameters,
the compiler will find it under the new rules because of ADL.
And some vendors don't care about their customers code anyway,
and don't mind breaking it.
<cut>
I wouldn't call it a bug. Technically, g++ is correct,
according to the standard. MSV++ is correct, according to
pre-standard conventions.
<cut>
The most typical use of the friend
function is for operator's, which have a parameter of the class
type, and in this case, ADL now picks up the name. (ADL wasn't
present in earlier C++.)
Is this "ADL" why the mighty Comeau compiler accepts neither (1) nor
(2)?
I'd have to see the exact error message to comment. The
standard is not always very clear, but if I understand it
correctly:

namespace N {
class C
{
friend void f() ;
} ;
}

Says that there exists a function void N::f(), and that it is a
friend of N::C, but it does not make this name visible outside
of the class.

The problem is probably:

void N::f() {}

According to the standard (§8.3): "When the declarator-id is
qualified, the declaration shall refer to a previously declared
member of the class or namespace to which the qualifier
refers,[...]". This seems to be saying that the above statement
is only legal if there is already a visible declaration of
N::f(). And there isn't. But the wording is anything but
clear.

The "usual" way of doing this is something like:

namespace N {
class C
{
friend void f() ;
} ;
extern void f() ;
}

This would typically be in a header, and the definition of
N::f() would be an a source file elsewhere; where really doesn't
matter. If you do this, there should be no problems.

And ADL has nothing to do with it, of course. ADL (argument
dependent lookup) only enters into play when the function has
arguments.

--
James Kanze (Gabi Software) email: ja*********@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

May 17 '07 #11
On May 17, 4:58 pm, James Kanze <james.ka...@gmail.comwrote:
The problem is probably:

void N::f() {}
Comeau says:
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 15: error: namespace "Me" has no member "you"
void Me::you(){}
^

"ComeauTest.c", line 18: error: namespace "Me" has no member "you"
Me::you();
^

2 errors detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed

These messages mean what they say, if 'friend' no longer injects a
name into an enclosing namespace.

Line 15 is the definition 'void Me::you(){}' above main()
Line 18 is the call 'Me::you();' in main()

All is clear. Thank you.

May 18 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: vijay | last post by:
Hello I wanted to understand a contradictory design of C++ class A {public: virtual void f(){ cout<<" base f"<<endl; } }; class B:public A {
2
by: nospam_timur | last post by:
I'm writing a Linux device driver that needs to compile with several different Linux versions. In my code, I need to reference certain functions by their address alone. Something like this: ...
6
by: Bill Rubin | last post by:
The following code snippet shows that VC++ 7.1 correctly compiles a static member function invocation from an Unrelated class, since this static member function is public. I expected to compile the...
10
by: bienwell | last post by:
Hi, I have a question about file included in ASP.NET. I have a file that includes all the Sub functions (e.g FileFunct.vb). One of the functions in this file is : Sub TestFunct(ByVal...
24
by: junky_fellow | last post by:
Hi, Is there any way, by which we can limit a specific function to be called only from a specific function ? I dont know the advantage of this. Someone asked this question from me in an...
28
by: Bill | last post by:
Hello All, I am trying to pass a struct to a function. How would that best be accomplished? Thanks, Bill
17
by: Jason Doucette | last post by:
I am converting a C-style unit into a C++ class. I have an implementation function that was defined in the .cpp file (so it was hidden from the interface that exists in the .h file). It uses a...
12
by: aaragon | last post by:
I have this scenario: several arrays for which I have their fixed values at compilation time. Now, at runtime I need to access a specific array depending on an integer but I want to avoid if and...
6
by: Rahul | last post by:
Hi Everyone, when a call to a function is done in a file and if the function isn't defined, compiler just assumes that it would return a int and that the definition would be available at some...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.