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