views:

134

answers:

2

As I noted in another SO question, I came across this article. The issue came up when I compiled boost 1.40 via MSVC7.1 and several C4251 warnings popped up.

Now, after reading said article, I wonder: Is it generally discouraged to export template code, e.g.

class DLLEXPORT_MACRO AClass
{
public:
   std::vector<int> getVecCopy() { return myVec; }
   ...
}

Say this code is compiled into a DLL via MSVC7.1. Though this code does not produce any errors when referenced from other MSVC7.1 code, it is said that referencing this DLL in MSVC8 code produces crashes at runtime (memory alignment issues?).

Since this obviously is bad...what is a "best practice" to cope with the issue of exporting template code?

A: 

Unfortunately there is really no way to export template code. External libraries typically just provide source code for any templates. Sometimes they have the templates use helper classes which are not templates to keep proprietary code hidden. But there's basically no way to do this.

rlbond
+6  A: 

This appears to be a bad idea, as std::vector differs or might differ between compiler versions. However, this can likely fail at load time, because the name mangling of std::vector should differ across compiler versions (that's part of the rationale for name mangling).

This link-time failure is something you can't really enforce as a developer though, other than buying compilers that support it. The other solution is to keep template types out of DLL interfaces entirely. Put them into private members.

Note that the problem is not unique to templates. Imagine for a moment that std::string is a UDT instead of a typedef, and provided by the compiler runtime. It could still change between compiler versions, and certainly between compiler vendors. It would still be unusable in a DLL interface.

For these reasons, the practical solutions are 0. use C, 1. use COM or 2. settle on a single compiler version.

MSalters
This is an aspect of general C++ ABI issues, of which the infamous "fragile base class" problem is another special case. Exporting a template interface from a DLL is just a catastrophe waiting to happen. My preferred solution is a variant of MSalters' 0: rather than exporting C++ directly from a DLL, provide a thin export layer with C bindings, with object pointers passed back and forth to the client as opaque handles. That way the client can't monkey directly with compiler-specific object internals, so it can't have this problem.
Bob Murphy
Thanks for the insight. While (1) won't be taken into consideration, I think I could live with (0) or (0') - as stated by Bob - respectively. In fact, I wonder why boost::program_options is creating a "catastrophe waiting to happen", though.
msiemeri