C4251警告をまじめに対応してはまった
昨日の続き。C4251警告について。
class Context { public: static std::auto_ptr<Context> GetInstance(){ return s_singleton; } Context(); ~Context(); private: struct Impl; std::auto_ptr<Impl> pimpl_; static std::auto_ptr<Context> s_singleton; };
もともとライブラリのヘッダがこんなだった場合。次のように書くとstd::auto_ptrがC4251警告になります。
#if DLLとしてビルドする場合 # define DLLIMPORT __declspec(dllexport) #else # define DLLIMPORT __declspec(dllimport) #endif class DLLIMPORT Context {//ここにimportを明記しないとs_singletonがリンクエラーになる public: static const std::auto_ptr<Context>& GetInstance(){ return s_singleton; } Context(); ~Context(); private: struct Impl; std::auto_ptr<Impl> pimpl_;//C4251警告! static std::auto_ptr<Context> s_singleton;//C4251警告! };
で、まじめに対応しようとすると、
struct Impl; friend class DLLIMPORT std::auto_ptr<Context>;//export!! friend class DLLIMPORT std::auto_ptr<Impl>;//export!! std::auto_ptr<Impl> pimpl_; static std::auto_ptr<Context> s_singleton;
とするとdllビルド時にstd::auto_ptrがexportされ警告が消えます。しかし!!
実際リンクしてみるとdll側にはstd::auto_ptrのdll内で実際に使われたメソッドしかexportされてない(というかtemplateが実体化していない?)のにこのクラス全体をimportすることになり、例えばdllでauto_ptr::getを使わずにリンク先のexeでContext::GetInstance().get()とか呼び出すと「未解決の外部シンボル」エラーになります。
ちなみにこんなんもかけますが、もっとひどいことになります。
template<typename T> class DLLIMPORT std::auto_ptr;//いっそテンプレートごとexport class DLLIMPORT { ... 以下略 ...
カンの良い人は想像できると思いますが、auto_ptrの実体すべてをdllからimportしようとします。もちろんそんなの無理です!
あー、なんかすげぇアホらしかった。疲れた。