Sign in to follow this  
Ryan_001

Legal C++?

Recommended Posts

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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
Quote:
Original post by no such user
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.


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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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.h
namespace Utils{
template<class T>
int doSomething(T param);
int doSomethingHelper(int param);
}

// Begin definitions

template<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 this post


Link to post
Share on other sites
Quote:
Original post by taz0010
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.h
namespace Utils{
template<class T>
int doSomething(T param);
int doSomethingHelper(int param);
}

// Begin definitions

template<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.


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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this