
On 7 May 2015 at 19:39, Andrey Semashev wrote:
It is a bad idea to dllexport templates as it greatly increases the chance of an ODR violation biting you in the ass (e.g. two internal private types with the same name). Nor is it ever necessary, as template implementation is always header only. Just leave templates, or any header implemented code, alone. Let them be compiled into a local implementation for every ELF object. Remove anything you really need to have exactly a single implementation of into a non-templated base class which is dllexported.
That's a very simplistic approach. In practice it is often needed to export a template specialization for different reasons: dependency hiding, compilation speedup, code size reduction, etc. Of course, there are complications and caveats but "just don't do it" is often not an answer.
Up until C++ 11 I really would say "just don't do it". The compiler doesn't know not to instantiate dllexported templates and does so anyway, so compilation speedup is zero. Marking templates with dllexport means the linker must deal with a ton more symbols to match up and remove because they aren't hidden, so you lose on link times too. The only potential win is code size reduction, and given that most compilers compile template instantiations into two variants, inlined at point of use and extern, the latter rarely actually gets used and is therefore thrown away by the linker anyway, so the gains are usually not worth the significant added hassle and brittleness for most libraries with most reasonably sized templates. Since C++ 11 we have extern templates, and that finally makes dllexporting template instantiations useful. I can see very significant potential benefits especially to compile and link times there, but a much superior implementation is to mark all common instantiations extern template in the headers and to supply a separate standalone library (without default hidden visibility) with all the common instantiations in one place. So you would have a two library solution there, one with with default hidden with the normal code and common template instantiations marked extern, and a second with default visible with the common template instantiations supplied. I hope that made sense. My point is, trying to do portable visibility management for templates from within a single library is likely much harder, much slower, and more brittle than a two library solution. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/