This is not a breaking issue but I like to clean my code from warnings so this is getting on my nerves.
I have been using the c++11 version of pimpl idiom to hide the class implementation for my library the usual way.
// dll header
class FrameworkImpl;
class EXPORT_API Framework
{
Framework(const Framework&) = delete;
Framework& operator=(const Framework&) = delete;
Framework(Framework&&) = delete;
Framework& operator=(Framework&&) = delete;
public:
Framework();
~Framework();
private:
std::unique_ptr<FrameworkImpl> impl_;
};
// application implementation
int main()
{
std::unique_ptr<Framework> test = std::make_unique<Framework>();
}
Everything will be fine, but I will keep getting the warning:
warning C4251: 'Framework::impl_': class 'std::unique_ptr<FrameworkImpl,std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'Framework'
So I tried have to add:
template class EXPORT_API std::unique_ptr<FrameworkImpl>;
Before the forward declaration but the warning would just change to:
warning C4251: 'std::_Unique_ptr_base<_Ty,_Dx>::_Mypair': class 'std::_Compressed_pair<_Dx,FrameworkImpl *,true>' needs to have dll-interface to be used by clients of class 'std::_Unique_ptr_base<_Ty,_Dx>'
I have being seeing this issue since VS2010 and I cannot figure a good way to fix this. No problems on gcc or clang and it would break my heart to use the old raw pointer version..
Instead of exporting the entire class, you could export public methods only:
The solution was to declare the constructor/destructor after the impl declaration and a combination of Olga Perederieieva answer
Please refer to this website for a detailed explanation and sample
Header:
Implementation:
That is a very common issue with DLL classes, that use templates from
std
.Why does it happen?
Reason is very simple: standard specifies only guarantees, limitations and requirements. So you can be sure, that every C++ 11 compiler will provide
std::unique_ptr
, that looks and works as described on this page. But everything else is implementation dependent.The main problem is, that different implementations may (and usually, will) use a totally different structure for particular types. They use additional helper variables, different layout and so on. This may differ even between two versions of the same compiler. So if client code touches in any way member variables of your class, you need to provide DLL interface for them. That applies recursively to all types used by
dllexport
ed class.You may want to read this article on MSDN, that describes this problem with containers in mind.
This problem can be simplified to the following:
dllexport
ed or use additional indirection withdllexport
ed methods.Further reading: