Re: A solution to warning C4251 - class needs to have dll-interface...?



On Tue, 16 Oct 2007 20:37:14 +0200, "Niels Dekker - no return address"
<unknown@xxxxxxxxxxxxxxx> wrote:

The following piece of code usually triggers warning C4251:
'MyClass::m_object' : class 'ThirdPartyTemplate<T>' needs to have
dll-interface to be used by clients of class 'MyClass':

template <typename T>
class ThirdPartyTemplate
{
public:
// Constructor.
ThirdPartyTemplate() {}
};

class __declspec(dllexport) MyClass
{
ThirdPartyTemplate<int> m_object; // warning C4251!
};

Is there really anything wrong about it?

It's nothing #pragma warning(disable) can't cure. :)

Here at LKEB (www.lkeb.nl), we
often get this kind of warning, when using Boost or STL. Now it appears
that one can get rid of the warning, by wrapping the ThirdPartyTemplate<int>
object inside a simple struct:

struct WrapperStruct
{
ThirdPartyTemplate<int> wrappedObject;
};

class __declspec(dllexport) MyClassWithoutWarning
{
WrapperStruct m_wrapper; // No warning! :-)
};

Does this approach really solve the problem, or does it only hide the
message?

It merely hides it. Think about the motivation for this warning. It's
emitted when you use a non-dllexported class X in a dllexported class Y.
What's so bad about that? Well, suppose Y has an inline function y_f that
calls a function x_f belonging to X that is not also inline. If y_f is
inlined inside some client that doesn't statically link X, the link will
fail, because x_f won't be found. Concerning your code, ThirdPartyTemplate
is a class template, and template code is generated wherever it's needed,
so this is not an issue. You may end up with some code bloat due to
duplicated template instantiations, but you can usually ignore this. There
are two workarounds (and I use that term lightly):

1. You can explicitly instantiate and dllexport the specializations you use
from some DLL, or more generally,

2. You can define a wrapper class that has no inline functions and defines
all the potentially compiler-generated functions (default ctor, copy ctor,
dtor, and assignment operator) and dllexport that.

It looks like you're sort of on your way to (2) with MyClass.

--
Doug Harrison
Visual C++ MVP
.



Relevant Pages

  • Re: unexpected public symbol in .obj for inlined function
    ... template <class Base> ... inline int DerivedClass::function ... here you only have the same inline function compiled twice in the ...
    (microsoft.public.vc.language)
  • Re: OK in Visual C++6.0 but not in Visual C++ .NET 2003?
    ... The instantion of the InitClass function template with template argument ... > If I had rewritten the friend declaration inside the class as ... i.e. MyClass and MyClassare the same. ... So this syntax means that all ...
    (microsoft.public.dotnet.languages.vc)
  • Template classes and containers
    ... I have a template class as below: ... template class myclass{ ... myclass{obj = new _T;} ... I need to keep all the myclass objects in a STL container such as ...
    (comp.lang.cpp)
  • Re: SFINAE compiler problem?
    ... struct myclass ... myclass& f1 ... template <typename T, typename X> ...
    (microsoft.public.vc.language)
  • Re: Template classes and containers
    ... > I need to keep all the myclass objects in a STL container such as ... > have a vector or myclass. ... STL or standard library container requires among other things that your ... > virtual in base since the return type depends on template resolution. ...
    (comp.lang.cpp)

Loading