Oleg Shirokikh
Oleg Shirokikh

Reputation: 3565

PIMPL: Exporting classes with single STL member (std::unique_ptr)

Suppose I have a class X with private implementation Ximpl:

//Proj.h

#ifdef PROJ_EXPORTS
#define PROJ_API __declspec(dllexport)
#else
#define PROJ_API __declspec(dllimport)
#endif


//X.h

class PROJ_API X
{
  void foo();
  //..
private:
  class Ximpl;
  std::unique_ptr<Ximpl> x_impl;
}

This works perfectly, but generates the warning:

Compiler Warning (level 1) C4251:

warning C4251: 'X::Ximpl' : class 'std::unique_ptr>' needs to have dll-interface to be used by clients of class 'X::Ximpl'

I have tried to follow the suggested MSDN article, but 1). it didn't work. 2) I don't clearly understand the solution(workaround)

Any advice/explanation on how to get rid of these warnings (#pragma disable's are not an option :) ).

Why is it Level 1 warning?

NOTE: It turns out that if Ximpl is not declared in X scope, then it's possible to export a unique_ptr<Ximpl> after forward-declaration of Ximpl, but if it's in Xs scope, then it's a nested class and therefore can't be forward-declared..

However, for templated class even above solution (have non-nested impl class), seems to fail:

//X.h

template<typename T>
class PROJ_API X
{
  T foo();
  //..
private:
  class Ximpl;
  std::unique_ptr<Ximpl> x_impl;
}

Upvotes: 2

Views: 1225

Answers (1)

Tonttu
Tonttu

Reputation: 1821

Make sure your class X exports and declares non-inlined destructor. Otherwise the compiler implicitly declares inline destructor, which needs to know something about Ximpl in order to call its destructor. And with inline destructor, users of X also need to know how to destroy std::unique_ptr, which leads to the warning.

You can confirm this by checking that ~Ximpl() isn't called when X gets deleted, unless you export non-inlined ~X().

Upvotes: 2

Related Questions