私の状況は次のとおりです。
ポインターやnew
. これは基本的に次のようになります。
struct null_t
{
// just a dummy
};
static const null_t null;
template<class T> class nullable
{
public:
nullable()
: _t(new T())
{}
nullable(const nullable<T>& source)
: _t(source == null ? 0 : new T(*source._t))
{}
nullable(const null_t& null)
: _t(0)
{}
nullable(const T& t)
: _t(new T(t))
{}
~nullable()
{
delete _t;
}
/* comparison and assignment operators */
const T& operator*() const
{
assert(_t != 0);
return *_t;
}
operator T&()
{
assert(_t != 0);
return *_t;
}
operator const T&() const
{
assert(_t != 0);
return *_t;
}
private:
T* _t;
};
比較演算子を使用すると、null_t
実際に値を取得する前にダミーが null に設定されているかどうかを確認したり、その値を必要として自動変換を行う関数に渡したりすることができます。
このクラスは、問題に遭遇するまで、かなり長い間役に立ちました。すべてファイル (この場合は XML) に出力されるいくつかの構造体を含むデータ クラスがあります。
だから私はこれらのような機能を持っています
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct1& value);
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct2& value);
それぞれが適切なデータで XML-DOM を埋めます。これも正しく動作します。
ただし、現在、これらの構造体の一部はオプションであり、コードでは として宣言されます。
nullable<MyDataStruct3> SomeOptionalData;
このケースを処理するために、テンプレートのオーバーロードを作成しました。
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const nullable<T>& value)
{
if (value != null) return Add(parent, name, *value);
else return parent;
}
私の単体テストでは、期待どおり、値または構造がnullable<T>
.
ただし、前述のデータ クラス (独自の DLL でエクスポートされる) を使用すると、何らかの理由で最後のテンプレート関数を初めて呼び出す必要があり、代わりに からnullable<T>
それぞれの型への自動変換T
が行われ、関数を完全にバイパスします。このケースを処理します。上で述べたように、すべての単体テストは 100% うまくいき、テストとコードを呼び出す実行可能ファイルの両方がデバッグ モードで MSVC 2005 によってビルドされています。
更新:明確にするために-オーバーロードされたAdd
関数はエクスポートされず、DLL 内で内部的にのみ使用されます。つまり、この問題が発生する外部プログラムには、テンプレートのオーバーロードされた関数を含むヘッドさえ含まれていません。