title: When exporting STL std::basic_string template from DLL, I get a LNK2005 error
body: <p>OK, so I've read several question and articles about this topic, and I feel like I understand the basics, but I'm still having trouble.</p>
  
  <p>I have a DLL that exports a class that has a std::string as a member.
  My main program contains classes that also have strings, and it uses the DLL.</p>
  
  <p>If I compile the DLL in VS2010, I get the following warnings:</p>
  
  <pre><code>warning C4251: 'MyClass::data' : class 'std::basic_string&lt;_Elem,_Traits,_Ax&gt;' needs to have dll-interface to be used by clients of class 'MyClass'
  </code></pre>
  
  <p>When I compile the EXE, I get the same warnings, but there are no errors, and the program compiles and runs.  In reality, it's a large project, so I get like 40 warnings, and I'm not too keen on that. (As a side-observation, these warnings are not present when compiled with VS2008)</p>
  
  <p>So, I read about that warning, and it lead me to this MS article:
  <a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;168958" rel="noreferrer">http://support.microsoft.com/default.aspx?scid=KB;EN-US;168958</a>
  which tells how to export a STL template from a DLL to satisfy the warnings I was getting.</p>
  
  <p>The problem is, when I add the following lines to remove the warnings:</p>
  
  <pre><code>EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator&lt;char&gt;;
  EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string&lt; char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;;
  </code></pre>
  
  <p>the DLL compiles with no warnings, but when I compile my EXE, the linker throws a fit:</p>
  
  <pre><code>2&gt;SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::~basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;(void)" (??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ) already defined in OtherClass.obj
  2&gt;SampleDLL.lib(SampleDLL.dll) : error LNK2005: "public: unsigned int __thiscall std::basic_string&lt;char,struct std::char_traits&lt;char&gt;,class std::allocator&lt;char&gt; &gt;::size(void)const " (?size@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIXZ) already defined in OtherClass.obj
  </code></pre>
  
  <p>Both the DLL and the EXE are compiled with the same code generation options.  I can use MT on both or MD, and the results are the same.</p>
  
  <p>I am including the code from a minimized sample program in case I left anything out above.</p>
  
  <p><strong>My main question: Can I fix the LNK2005 errors, or is it safe to just ignore the C4251 warnings?</strong></p>
  
  <p><strong>Edit:</strong> So I've read a little more, and it looks like if the std::string that the DLL class uses is a private variable that is only accessed by member functions, it may be safe to ignore the warning...  Any comments on this?  Is this a step in the right direction?</p>
  
  <p>DLL code: 
  </p>
  
  <pre><code>#pragma once
  
  #include &lt;exception&gt;
  #include &lt;string&gt;
  
  
  #ifdef SAMPLEDLL_EXPORTS
  #    define DECLSPECIFIER __declspec(dllexport)
  #    define EXPIMP_TEMPLATE
  #else
  #    define DECLSPECIFIER __declspec(dllimport)
  #    define EXPIMP_TEMPLATE extern
  #endif
  
  //disable warnings on extern before template instantiation (per MS KB article)
  #pragma warning (disable : 4231)
  //std::basic_string depends on this allocator, so it must also be exported.
  EXPIMP_TEMPLATE template class DECLSPECIFIER std::allocator&lt;char&gt;;
  //std::string is a typedef, so you cannot export it.  You must export std::basic_string
  EXPIMP_TEMPLATE template class DECLSPECIFIER std::basic_string&lt; char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;;
  #pragma warning (default : 4231)
  
  class DECLSPECIFIER MyClass
  {
  public:
      std::string getData(); //returns 'data', body in CPP file
  private:
      std::string data;
      int data2;
  };
  
  //in SampleDLL.cpp file...
  std::string MyClass::getData() { return data; }
  </code></pre>
  
  <p>EXE code:
  </p>
  
  <pre><code>#include &lt;iostream&gt;
  #include "SampleDLL.h"
  
  using namespace std;
  
  void main()
  {
      MyClass class1;
  
      cout &lt;&lt; class1.getData() &lt;&lt; endl;
  
  }
  </code></pre>