a possible compiler bug

Started by
5 comments, last by bjogio 18 years, 11 months ago
Hi guys I have a template like this:

//File "foo.h"
template<typename T>
class foo
{
   T flarp;
   void bar();
   //implementation doesn't matter
};


and then:

//File "foo.cpp"
template<typename T>
void foo::bar<T>()
{
   std::cout << "bau";
}


my compiler "MS VC++ .NET 2003 Toolkit" give me LNK2001 if I compile this example. Looking at MSDN I've discovered that Ms compiler do not allow outside template member declaration even not if declared "inline". I HAVE to declare all the members inside my class. The question is: in MSDN seems that the compiler affected by this poor limitation are the series up to the 2002 .NET but the 2003 give me this error, why? If even the 2003 is affected by this bug why this can happen? the Ms compiler is widely used and it cannot lack this standard guaranteed feature! [Edited by - bjogio on May 16, 2005 2:33:20 AM]
[ILTUOMONDOFUTURO]
Advertisement
This is a problem for (allmost) all current C++ compilers. The problem is that foo::bar is being implemented in a completely seperate compilation unit. You can either manually instantiate them (which requires manual handwork), or simply have them appear in the same scope by following a pattern like so:

//foo.hh#ifndef IC__FOO#define IC__FOOtemplate < typename T >class t_foo{    void bar( void );    template < typename T2 > void t_bar( void );};class foo{    void bar( void );    template < typename T > void t_bar( void );};#include "foo.tcc"#nedif //ndef IC__FOO//foo.tcc//all template dependant functions:template < typename T >void t_foo< T >::bar( void ){}template < typename T1 , typename T2 >void t_foo< T1 >::t_bar< T2 >( void ){}template < typename T >void foo::t_bar< T >( void ){}//foo.cc//all non template functions:void foo::bar( void ){}


I believe most compilers will simply drop multiple definitions of the same template class.

For an overview of methods used to solve the template instantiation problem, see http://www.dis.com/gnu/gcc/Template-Instantiation.html
woa, I didn't know, your solution is a little tricky but if it's the only way to manage this I would implement that. The main problem about my program is that I use a stringstream in my template class and I don't want to #include <sstream> in my .h cause all the .cpp that will use this header will use implicity the <sstream> (that is bad for compilation time and style). Thanks
[ILTUOMONDOFUTURO]
Quote:Original post by bjogio the Ms compiler is widely used and it cannot lack this standard guaranteed feature!


Except of course that it is not a standard feature. The C++ Standard does not require that compilers provide template instantiation implementations across translation units.

Unless of course I read it wrong. Which is entirely likely too.

Quote:Original post by Phillip Martin
Quote:Original post by bjogio the Ms compiler is widely used and it cannot lack this standard guaranteed feature!


Except of course that it is not a standard feature. The C++ Standard does not require that compilers provide template instantiation implementations across translation units.

Unless of course I read it wrong. Which is entirely likely too.


I'm pretty sure it's not a standard feature--enter the "export" keyword that's only been implemented on one C++ compiler to my knowledge.

[Edited by - mhamlin on May 16, 2005 4:08:20 AM]
Quote:Original post by bjogio
woa, I didn't know, your solution is a little tricky but if it's the only way to manage this I would implement that. The main problem about my program is that I use a stringstream in my template class and I don't want to #include <sstream> in my .h cause all the .cpp that will use this header will use implicity the <sstream> (that is bad for compilation time and style). Thanks


It's definately an issue. My suggestion is to compartmentalize as much as you can. For example, at one point I was working on writing a toy compiler, in which I had a complex grammar defined using boost::spirit. It was a template heavy piece of work, and had a lot of code that needed to be declared in the class definition. To parse an example file, I had something like:

file_iterator<> begin ( filename );
file_iterator<> end = begin.make_end(); //ugly, but that's how boost does it :-/.
parse( begin , end , evo_grammar( ast_tree ) );

where evo_grammar was the huge and monsterous piece of template mojo. Since this was in my main.cc file, it tacked on 20 seconds to every time I made a change in the overall flow of the program. I solved it by moving this statement out into it's own function. The code became something like:

file_iterator<> begin ( filename );
file_iterator<> end = begin.make_end();
compile_into( begin , end , ast_tree );

Now, the only function that needed to access the evo_grammar class and it's template pile was compile_into, which I placed in it's own source file. This meant that I only had to recompile the template code when there was an actual change to that area. Instead of making public the complex AND template heavy parts of the code, I compartmentalized it into a private section.

Just another possible method for solving related problems.
If I remember well in Stroustrup C++ book (I don't know the american title sorry) there is somewhere an example template with:
template<typename T>
void aclass::amethod<T>()
{
//blah
}
but I don't remember if it is simply a piece of code from the same translation unit (for sure it is). I loved template but now that I've discovered this limitation (that break the laws of a well designed modular software) I think that I will try another solution. What a pain. Next time I will study the problem more by myself before writing in the forum.

[ILTUOMONDOFUTURO]

This topic is closed to new replies.

Advertisement