how to correctly return std::list from dll

2019-07-22 09:53发布

问题:

the project has this structure: 1. Dll - with core logic and class hierarchy 2. exe - console app which processes commandline and starts the algorithms 3. Dll - tests, like a unit test kit - hardcoded filling up the collection of the ojects from first Dll and passes the collection to exe console to process

so Dll point 3 should return the collection (e.g. std::list), the collection contains polymorphic objects, then should store the pointer, I'd prefer to use std::unique_ptr instead of raw pointers

I see that unique_ptr supports move semantic only and I'm filling up the list using emplace_back member. however there is a problem to return std::list> collection from Dll related with MSVC class exporting technique

if I understand this right : shared between dll and exe projects header should contain something like this where EXP_DLL should be defined for Dll and undefined for exe

 #ifdef EXP_STL
 #    define DECLSPECIFIER __declspec(dllexport)
 #    define EXPIMP_TEMPLATE
 #else
 #    define DECLSPECIFIER __declspec(dllimport)
 #    define EXPIMP_TEMPLATE extern
 #endif

 EXPIMP_TEMPLATE template class DECLSPECIFIER std::list<std::unique_ptr<MyBassClass>>;

 std::list<std::unique_ptr<MyBassClass>> DECLSPECIFIER make_test_array();

this definition:

 EXPIMP_TEMPLATE template class DECLSPECIFIER std::list<std::unique_ptr<MyBassClass>>;

raises the error

C2280:std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function

I see the attempt to call copying ctor of unique_ptr (of course, deleted)

could you clarify these questions for me:

  1. how this export declaration of instantiated template can call copying ctor here?
  2. could you suggest the solution how to avoid this ?

回答1:

Assuming the following conditons are met:

  1. All projects in the solution link the same run-time DLL (/MD option)
  2. Class MyBaseClass is attributed with DECLSPECIFIER.
  3. Class MyBaseClass is completely defined before make_test_array declaration.

you must not export template specialization at all. Just remove the line EXPIMP_TEMPLATE template class .... std::list and std::unique_ptr code will be inlined. You will get warning C4251, ignore it.

When you try to export std::list specialization, all std::list<T> methods are instantiated. Some of them (e.g. assignment operator) require T to be copyable. That's why specialization with unique_ptr can't be compiled.