IWETHEY v. 0.3.0 | TODO
1,095 registered users | 0 active users | 0 LpH | Statistics
Login | Create New User
IWETHEY Banner

Welcome to IWETHEY!

New g++ question
(And Todd, you can join in if you want, too...just keep the vitriol to digestible quantities).

OK, so how does GCC's C++ compiler allow one to compile a templated class's methods in a separate file (other than the header)?

According to Stroustup's The C++ Programming Language, you can specify a "separate compilation strategy" (which he goes on to detail...it's the standard declarations in the header, definitions in the source file strategy known to everyone except dyed-in-the-wool Java programmers). Then he states:
Note that to be accessible from other compilation units, a template definition must be explicitly declared export (\ufffd9.2.3). This can be done by adding export to the definition or to a preceding declaration. Otherwise the definition must be in scope wherever the template is used

OK, kewl! So I place the methods of the templated class in a .cxx file (.cxx is our local choice for the extension of C++ source files), and feed it to GCC. GCC is not pleased; it squaks something about the keyword (and it recognizes it as a keyword, at least) export is not implemented, and will be ignored. Which is then followed by a large amount of noise about not finding the methods in the .cxx file, multiplied by all the templated instances.

OK, so this means that templated classes must be fully implemented in the .h files, right? Well, not quite. You see there is this thing called the STL (among other things, especially by Todd). Given this, the STL should be fully and completely implemented in its headers (after all, the STL for a given version of GCC is compiled in that version of GCC.) Yet, poking around in the STL headers shows that some templated methods of the STL classes are indeed implemented in separate compilation units. But how? I don't have the source to figure this out. So does anybody out there know GCC's magic incantation that, when translated into ANSI C++, becomes export?

(BTW, this is a GCC 3.3.4 compiler, so we're talking about a version that is relatively recent.)

thanx-
jb4
shrub●bish (Am., from shrub + rubbish, after the derisive name for America's 43 president; 2003) n. 1. a form of nonsensical political doubletalk wherein the speaker attempts to defend the indefensible by lying, obfuscation, or otherwise misstating the facts; GIBBERISH. 2. any of a collection of utterances from America's putative 43rd president. cf. BULLSHIT

New You can't get there from here
Start reading here: [link|http://www.network-theory.co.uk/docs/gccintro/gccintro_59.html|http://www.network-t.../gccintro_59.html]

After clicking 'next' a couple of times you come to:

7.4.4 The export keyword

At the time of writing, GCC does not support the new C++ export keyword (GCC 3.4.4).

This keyword was proposed as a way of separating the interface of templates from their implementation. However it adds its own complexity to the linking process, which can detract from any advantages in practice.

The export keyword is not widely used, and most other compilers do not support it either. The inclusion compilation model described earlier is recommended as the simplest and most portable way to use templates.


IOW, just put the code in the headers (or include the template's .c file in the template class's header file).

Templates are a bitch for the compiler to work out. Older systems I've used tried to be clever about it and would compiler everything, then try to link, an awk script would process the linker error messages, then generate some code, compile that and add it to the link. Given that linkers don't always exhaustively report all link errors, this was an iterative process that resulted in a 2 hour build rocketing up to over 24 hours in one pathological case. Rewriting templates as inline wrappers around C style code that required sizes as parameters everywhere moved the build time back to about 2 hours. IOW we did something like this:

class UnsafeArray
{
size_t _length;
size_t _capacity;
size_t _itemSize;
void* _data;
public:
UnsafeArray(size_t itemSize, size_t capacity) : _length(0), _capacity(capacity), _itemSize(itemsize), _data(malloc(_capacity*_itemSize)) {}

virtual ~UnsafeArray() { free(_data); }
};

template <class T>
class Array : private UnsafeArray
{
public:
Array(size_t capacity) : UnsafeArray(sizeof(T),capacity) {}
...
};

You get the idea - do the real work in real code and put syntactic sugar/type checking on it for the girly programmers (like me - pre coffee).



"Whenever you find you are on the side of the majority, it is time to pause and reflect"   --Mark Twain

"The significant problems we face cannot be solved at the same level of thinking we were at when we created them."   --Albert Einstein

"This is still a dangerous world. It's a world of madmen and uncertainty and potential mental losses."   --George W. Bush
Expand Edited by tuberculosis Aug. 21, 2007, 06:14:20 AM EDT
New You gotta go around
(...which describes perfectly the concept of driving in Portland OR, but I digress....)

But that still doesn't explain how GCC manages to get STL class methods to compile in an external compilation unit (in GCC 3.3.4)
jb4
shrub●bish (Am., from shrub + rubbish, after the derisive name for America's 43 president; 2003) n. 1. a form of nonsensical political doubletalk wherein the speaker attempts to defend the indefensible by lying, obfuscation, or otherwise misstating the facts; GIBBERISH. 2. any of a collection of utterances from America's putative 43rd president. cf. BULLSHIT

New Did you read the bit about explicit instantiations?
[link|http://www.network-theory.co.uk/docs/gccintro/gccintro_60.html|http://www.network-t.../gccintro_60.html]

Explicit instantiation can also be used to make libraries of precompiled template functions, by creating an object file containing all the required instantiations of a template function (as in the file 'templates.cc' above). For example, the object file created from the template instantiations above contains the machine code needed for Buffer classes with 'float', 'double' and 'int' types, and could be distributed in a library.


I wouldn't be surprised if STL didn't ship with a pre-built library for all native types constructed by including all the source in one big file with explicit instantiations and compiling it down to a lib.

Are you dead sure that the headers don't include the source?



"Whenever you find you are on the side of the majority, it is time to pause and reflect"   --Mark Twain

"The significant problems we face cannot be solved at the same level of thinking we were at when we created them."   --Albert Einstein

"This is still a dangerous world. It's a world of madmen and uncertainty and potential mental losses."   --George W. Bush
Expand Edited by tuberculosis Aug. 21, 2007, 06:14:56 AM EDT
New Yes, but I didn't think it applied
How in the world could the STL precompile for a list of pointers to maps, eahc of which uses an unsigned int for a key value and a pointer to a deque of unsigned longs as the target value? To wit:

\ntypedef list<(map<uint32_t, deque<uint32_t> * >)*>\n


I think you'll agree that that permutation isn't likely to occur as a "standard" one. Yet that would have to be one of them if they have predefined the list code, because the erase() method of a list (for instance) is not in the header.

As far as being dead sure, well...as you are most probably aware, the authors of every STL I've ever seen the headers for are the anti-Dickens of the coding world (i.e. they get paid in inverse proportion to the number of keystrokes used)...It's just plain gawd-awful. I'd summarily fire any programmer who wrote code like that in my shop! Nonetheless, grep is my friend and so searching the entire file for the names of functions that are in the interface, it will occasionally find ones that are not defined. For example, this member function declaration taken from stl_list.h:

\n      iterator\n      erase(iterator __position);\n\n


erase is a function taking an iterator and returning an iterator. But no code...just a declaration.
template<typename _Tp, typename _Alloc = allocator<_Tp> > iterator list<_Tp, _Alloc>::erase (iterator __position) would have to be defined elsewhere, for specific types of both _Tp and _Alloc, or the linker wouldn't find it.
jb4
shrub●bish (Am., from shrub + rubbish, after the derisive name for America's 43 president; 2003) n. 1. a form of nonsensical political doubletalk wherein the speaker attempts to defend the indefensible by lying, obfuscation, or otherwise misstating the facts; GIBBERISH. 2. any of a collection of utterances from America's putative 43rd president. cf. BULLSHIT

New If you know the specializing classes in advance
you can specialize template in your .cpp file. This way, the method bodies can be kept in .cpp files as well.

Something along the line

------------------ Class.h ------------
template <class T>
class Class
{
void f();
};

--------------------Class.cpp -----------

template <class T>
void Class<T>::f()
{
// do something
}

template class Class<int>;

template class Class<bool>;

and so on.

Please see [link|http://gcc.gnu.org/onlinedocs/gcc-4.0.2/gcc/Template-Instantiation.html#Template-Instantiation|http://gcc.gnu.org/o...ate-Instantiation] for complete discussion. They have another method in there that may be more suitable for you, but it's a method I've never used...


------

179. I will not outsource core functions.
--
[link|http://omega.med.yale.edu/~pcy5/misc/overlord2.htm|.]

New Sounds like the STL was build using -frepo
which (if I read the documentation correctly) would cause additional object files to be emitted that are then linked together by the linker.

Thanks for the link, Ark!
jb4
shrub●bish (Am., from shrub + rubbish, after the derisive name for America's 43 president; 2003) n. 1. a form of nonsensical political doubletalk wherein the speaker attempts to defend the indefensible by lying, obfuscation, or otherwise misstating the facts; GIBBERISH. 2. any of a collection of utterances from America's putative 43rd president. cf. BULLSHIT

     g++ question - (jb4) - (6)
         You can't get there from here - (tuberculosis) - (3)
             You gotta go around - (jb4) - (2)
                 Did you read the bit about explicit instantiations? - (tuberculosis) - (1)
                     Yes, but I didn't think it applied - (jb4)
         If you know the specializing classes in advance - (Arkadiy) - (1)
             Sounds like the STL was build using -frepo - (jb4)

The tautological prime conjecture states that the tautological prime conjecture is true.
59 ms