function template instantiation
Hi all, I've been using Boost.Python to expose some instances of a class template to a python module. I ran into a problem with my class's method templates not being instantiated, leading to "undefined symbol" on import. Actually, this message from back in 2004 describes the problem exactly: http://mail.python.org/pipermail/cplusplus-sig/2004-February/006586.html The advise is to move the method definitions into the header file, but I have some methods I want to ensure are not inlined, so I ended up using explicit template instantiations instead. Kind of a pain. The standard has this to say about function template instantiations: 14.7.1 Implicit instantiation 2. Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist. So my question is, why isn't taking the address of some instance of a templatized function and passing it to def() enough to require the function definition to exist? Should this be considered a usability bug in the library, a problem with my compiler, or maybe neither? I'm using gcc 4.4. Thanks, Kyle Cronan
Kyle, On 03/29/2012 05:14 PM, Kyle Cronan wrote:
So my question is, why isn't taking the address of some instance of a templatized function and passing it to def() enough to require the function definition to exist?
It certainly is enough to require, but isn't enough to magically make a definition to appear. Either you provide the definition in the header, and let the compiler do that magic of instantiating the template on-demand, or you defer to a separate compilation unit, but then can't rely on such magic and need to explicitly instantiate.
Should this be considered a usability bug in the library, a problem with my compiler, or maybe neither?
I haven't seen your specific code, but your description sounds like all is working as expected. Stefan -- ...ich hab' noch einen Koffer in Berlin...
On Thu, Mar 29, 2012 at 4:42 PM, Stefan Seefeld <stefan@seefeld.name> wrote:
It certainly is enough to require, but isn't enough to magically make a definition to appear. Either you provide the definition in the header, and let the compiler do that magic of instantiating the template on-demand, or you defer to a separate compilation unit, but then can't rely on such magic and need to explicitly instantiate.
Makes sense, thank you. Hopefully, having this in the list archive will help others in the future. Somehow I had never run into the need to use explicit instantiation before! But I think I get it now: by the time the linker sees what's going on it's too late to generate the necessary object code. Best, Kyle
(answering off-list) Kyle Cronan schrieb am Thu, 29. Mar 2012, um 16:14:04 -0500:
... but I have some methods I want to ensure are not inlined ...
Note that this is impossible. The compiler is free to inline *any* function. If the address of a function is taken, the compiler must emit code for a non-inlined version, but this is independent from whether the function is defined inline or not. And even if a non-inlined version is present, the compiler still can inline other calls. Bottom line: it doesn't matter whether you define functions in the header or not, at least as far as inlining in concerned. Cheers, Sven
On 29 Mar 2012 at 16:14, Kyle Cronan wrote:
So my question is, why isn't taking the address of some instance of a templatized function and passing it to def() enough to require the function definition to exist? Should this be considered a usability bug in the library, a problem with my compiler, or maybe neither?
No, in that earlier post this behaviour is by design and intent (and I'm surprised no one said so at the time). When you do this: class_< field<vect> >("field_vect", init< int >()) .def("getsize", &field<vect>::getsize) ; ... you're telling the compiler to instantiate field<vect>::getsize. Problem is, the compiler hasn't seen what getsize is supposed to be because its implementation was declared in a separate compilation unit. Therefore it can't know how to mangle the symbol for field<vect>::getsize, and therefore can't resolve the symbol. Besides the above, you should NEVER declare template implementations outside a header file. Otherwise it easily leads to violations of the ODR. The old export keyword was supposed to solve the problem of having to declare template implementations in headers, but that's dead as a concept now. BTW, regarding inlining, there are magic attributes to force never inlining. Very, very useful for debugging optimised code, and easier and clearer to use those than obfuscating the code. HTH, Niall -- Technology & Consulting Services - ned Productions Limited. http://www.nedproductions.biz/. VAT reg: IE 9708311Q. Work Portfolio: http://careers.stackoverflow.com/nialldouglas/
participants (4)
-
Kyle Cronan -
Niall Douglas -
Stefan Seefeld -
Sven Marnach