【发布时间】:2011-01-25 08:39:16
【问题描述】:
我的情况如下:
我有一个模板包装器,它可以处理值和对象可以为空的情况,而无需手动处理指针甚至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> 自动转换为相应的类型 @987654329 @ 完成,完全绕过了处理这种情况的函数。正如我上面所说的 - 所有单元测试都 100% 正常,测试和调用代码的可执行文件都是由 MSVC 2005 在调试模式下构建的 - 这个问题绝对不能归因于编译器的差异。
更新:澄清 - 重载的 Add 函数不会导出,仅在 DLL 内部使用。也就是说,遇到这个问题的外部程序甚至不包括带有模板重载函数的头部。
【问题讨论】:
-
你在定义命名空间吗?您的定义位于哪个命名空间中?图书馆呢?
-
您可能需要查看
boost::optional,以获得强大而完整的解决方案。 -
@GMan:是的,这与
nullable所做的非常相似,但是boost::optiona具有相同的自动转换行为,因此无法解决当前的问题。
标签: c++ templates overload-resolution