# Legal C++?

## Recommended Posts

Ryan_001    3475
I was playing around and found that:
struct Test {
void f1 () { f2(); }
void f2 () { cout << "Test::f2()" << endl; }
};


Compiles and runs find in VC++ express (2010 beta version). I was under the impression that it should not compile (f2 should be undefined for f1). Is the above legal C++?

##### Share on other sites
Antheus    2409
Member functions are defined as part of interface, and they are all known in advance. Placement of bodies is merely another way to hint or demand inline.

In C, functions are parsed top-to-bottom, and even that might not hold for recent revisions. Hence the need for forward declarations.

The parsed equivalent is this:
struct Test {   void f1 ();   void f2 ();   };void Test::f1 () { f2(); }void Test::f2 () { cout << "Test::f2()" << endl; }

IIRC, standard might disagree.

##### Share on other sites
no such user    280
The relevant part of the standard seems to be section 9.2 paragraph 2 which states that inside function definitions inside the class definition the complete type of the class is used.

##### Share on other sites
Ryan_001    3475
Quote:
 Original post by no such userThe relevant part of the standard seems to be section 9.2 paragraph 2 which states that inside function definitions inside the class definition the complete type of the class is used.

Thank-you, that's good to know.

I thought C++ was designed so at least (in theory) it was possible to parse in a single pass. At the very least that would require the caching of the function bodies till after.

##### Share on other sites
taz0010    277
Code marked inline (either with the keyword or placing the body with the declaration) is given internal linkage, meaning you're allowed to provide the body in every translation unit, and in fact have to do so. I wonder if people ever use the inline keyword to gain that behavior instead of for the optimisation, which the compiler will probably ignore anyway!

##### Share on other sites
osmanb    2082
Yes, technically people do that all the time, although you might not realize it. Template functions are the really obvious example. In theory you can explicitly instantiate them in a single translation unit, but almost no one does that. Most people just put all their template code into headers, even when the function bodies are much larger and more complex than any compiler's inlining threshold.

##### Share on other sites
taz0010    277
A while back I was writing some template code that ended up calling a function which was part of the process, but not itself a template. The compiler was giving "symbol already defined" errors on the non-template function. My code looked something like this:

// Utils.hnamespace Utils{	template<class T>	int doSomething(T param);	int doSomethingHelper(int param);}// Begin definitionstemplate<class T>int Utils::doSomething(T param){	...}int Utils::doSomethingHelper(int param){	...}

I solved it by moving doSomethingHelper out to it's own cpp file, but I suppose I could have marked it inline to give it internal linkage like the template functions have.

##### Share on other sites
phresnel    953
Quote:
 Original post by taz0010A while back I was writing some template code that ended up calling a function which was part of the process, but not itself a template. The compiler was giving "symbol already defined" errors on the non-template function. My code looked something like this:// Utils.hnamespace Utils{ template int doSomething(T param); int doSomethingHelper(int param);}// Begin definitionstemplateint Utils::doSomething(T param){ ...}int Utils::doSomethingHelper(int param){ ...}I solved it by moving doSomethingHelper out to it's own cpp file, but I suppose I could have marked it inline to give it internal linkage like the template functions have.

Yes, because you haven't stated in the code that doSomethingHelper() has internal linkage. So yes, the solution is to either make it inline, or to move it to a cc-file.

And if your intention is to make a template inline (member) function, then you should also mark that as inline or define it inside the class.