bizarre extra header file inclusion

I've got a program foo/foo.cc, that includes the following code, stripped down for clarity:

#include "../bar/bar.h"

func ()

{

update_status = update_jobs_table <SequenceIndex, Job_list_by_Sequence::const_iterator>

(jobs_table_update_statement, Normally_Changed_Job_list, UPDATE_CHANGE_DATA);

}

bar.h includes the following template definition:

template <typename Job_bunch_index, typename Job_bunch_const_iterator, typename Job_bunch>

int update_jobs_table (PREPARED_STATEMENT update_stmt, Job_bunch &Updated_Job_bunch, enum jobs_table_update_type update_type);

Now here's the really bizarre part. When I'm in the foo directory and I compile foo.cc

with CC from Sun Studio Express 2 - August 2006, the bar.h header file is included twice

within the compilation: once at the #include, and once at the very end of foo.cc, where

there is no #include at all !!

I can tell where the inclusions are happening by judicious insertion of #if, #define,

and #warning directives, and I can tell it's the processing of this template invocation

that's causing the problem by commenting it out.

It gets scarier yet. If I move bar.h from the bar directory to the foo directory,

and use either

#include "../foo/bar.h"

or

#include "bar.h"

then this double inclusion goes away. Why it would depend on the inclusion path

is truly mystifying.

[1488 byte] By [herteg] at [2007-11-26 11:59:33]
# 1
I'm not 100% sure, but you might find a clue by looking at CC(1) near "extdef" option.
MaximKartashev at 2007-7-7 12:21:36 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 2

Do you have bar.cc in the bar directory? I try to reproduce your problem but do not get success. If bar.h included twice compiler would show error message about multiple declaration of class S.

[code]

% cat bar/bar.h

#ifndef BAR_H

#define BAR_H

template <typename T>

struct S

{

S();

};

template <typename T>

S<T>::S()

{}

#endif

% cat foo/foo.cc

#include "../bar/bar.h"

int main()

{

S<int> s;

}

% cd foo

% CC foo.cc

[/code]

Atanasyan at 2007-7-7 12:21:36 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 3

I suspect you are seeing an effect of automatic file inclusion as part of template processing. The compiler behavior is discussed in detail in the C++ Users Guide chapter on using templates. Here is a brief summary:

If a header bar.h includes a template declaration and the compiler needs to see the definition, it looks for an associated bar.cc file and automatically includes it. This feature -- present in the original Cfront compiler from AT&T and in all Sun compilers -- allows you to separate template declarations from definitions, and omit processing the definitions when they are not needed. You don't have to do anything special to get the definitions included when they are needed.

Because of this compiler behavior, you have to follow some rules about file naming.

If a file bar.h contains any template declarations without definitions, an associated file bar.cc (or bar.cpp, bar.C, bar.cxx, bar.c++) must contain definitions for one or more of those templates, and NOTHING else, except possibly header files needed by bar.cc that are not included in bar.h. You do not compile bar.cc directly, and bar.cc in particular must not include bar.h. File bar.h should have the usual guards against multiple inclusion.

clamage45 at 2007-7-7 12:21:36 > top of Java-index,Development Tools,Solaris and Linux Development Tools...