help-gplusplus
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Explicite Template Instantiation and Inline


From: Paul Pluzhnikov
Subject: Re: Explicite Template Instantiation and Inline
Date: Fri, 18 May 2007 17:25:20 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) XEmacs/21.4 (Jumbo Shrimp, linux)

tthunder@gmx.de writes:

> Some compilers really compile it.

It compiles fine. It just doesn't link.

> VC71, BCB 2006
> It works.

I have no clue what 'BCB 2006' is, but VC71 fails to link it just
like most of the other compilers:

$ cl junk.cpp   # junk.cpp is the code you posted, *verbatim*

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

junk.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:junk.exe
junk.obj
junk.obj : error LNK2019: unresolved external symbol "void __cdecl 
doFunc<bool>(void)" (??$doFunc@_N@@YAXXZ) referenced in function "private: void 
__thiscall foo<bool>::notUsed(void)" (?notUsed@?$foo@_N@@AAEXXZ)
junk.exe : fatal error LNK1120: 1 unresolved externals


> If g++ does not generate the code for "foo<bool>::notUsed()", how does
> g++ know that "doFunc<bool>()" is needed.

But g++ *is* generating the code (because you asked it to):

$ /usr/local/gcc-3.4.6/bin/g++ -c junk.cpp
$ nm junk.o
         U _Z6doFuncIbEvv
00000000 W _ZN3fooIbE7notUsedEv
         U __gxx_personality_v0
00000000 T main
$ nm -C junk.o
         U __gxx_personality_v0
00000000 T main
         U void doFunc<bool>()
00000000 W foo<bool>::notUsed()     <<< see! that's the generated code


> NO, of course I don't want to instantiate foo<bool>::notUsed().

In that case, *why* are you asking compiler to instantiate it (with
explicit template instantiation request)?

> Instantiating "foo<bool>::notUsed()" would instantiate
> "doFunc<bool>()". Unfortunatelly, "doFunc<...>()" does not work for
> "bool". Therefore, using "notUsed()" for type "foo<bool>" should be
> prohibited.

The way to prohibit its instantiation is to provide a specialization
that does not compile (compile-time assert) or that aborts at
runtime.

> For "VC71" and "BCB 2006" the way shown in the example works:
> a) I do not use "foo<bool> obj; obj.notUsed();"
>   => links well

Your code does *not* link with VC71. You are not telling the whole story.

> b) I use "foo<bool> obj; obj.notUsed();"
>   => linker error (exactly what I want, because notUsed() is not
> available for foo<bool>)
>
> With g++ case (a) does not link :(

Case (a) will link just fine if you remove explicit instantiation
request:

$ cat junk.cpp
template <typename T> 
void doFunc(); 
 
template <typename T> 
struct foo 
{ 
        void notUsed(); 
}; 
 
template <typename T> 
inline void foo<T>::notUsed() 
{ 
        doFunc<T>();   // <---- Linker cannot find doFunc<bool>() 
} 
 
// template class foo<bool>;  // <<< BOGUS instantiation request
 
int main() 
{ 
#if USE_FOO_BOOL
   foo<bool> obj;
   obj.notUsed(); // should fail to link
#endif
   return 0; 
} 

$ /usr/local/gcc-3.4.6/bin/g++ junk.cpp && echo ok
ok                                  # links just fine

And case (b) will fail:

$ /usr/local/gcc-3.4.6/bin/g++ junk.cpp  -DUSE_FOO_BOOL
/tmp/ccspuWsG.o: In function `foo<bool>::notUsed()':
/tmp/ccspuWsG.o(.gnu.linkonce.t._ZN3fooIbE7notUsedEv+0x7): undefined reference 
to `void doFunc<bool>()'
collect2: ld returned 1 exit status

So it seems to me that g++ will already do exactly what you want
IFF you remove the explicit instantiation request.

Cheers,
-- 
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]