以下是Boost.Python的source code:
的片段template <class T> struct null_ok; // how's it working?
template <class T>
inline null_ok<T>* allow_null(T* p)
{
return (null_ok<T>*)p;
}
没有前向声明的struct null_ok
的定义,而null_ok
与模板参数T
无关。
在Python wiki中,给出了一些提示:
处理&LT;&GT; y(null_ok(x))允许y变为NULL
处理&LT;&GT; y(x),其中x不是null_ok的结果,永远不会导致NULL y。如果x为NULL
,则抛出异常
我无法弄清楚结构模板null_ok
的声明(没有定义)如何达到上述目的?
答案 0 :(得分:4)
重点是编码&#34;这个指针可以为null&#34;以及指针本身类型中的原始类型。
然后,接受指针的函数模板可以重载以识别null_ok<T>*
指针,而不是空指针错误(将其转换回T*
)。
您不需要null_ok
的定义,因为您可以指向不完整的类型,并且可以防止人们意外地编写null_ok<int> a;
之类的内容。
答案 1 :(得分:1)
正好使用您的代码段下面的handle.hpp
中的代码(我的评论):
// this is a borrowed handle which can be null,
// so increment refcount if p is not null
// (xincref just does nothing in this case)
template <class T>
inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int)
{
return python::xincref((T*)p);
}
// the same - as stated in the doc, null_ok and borrowed are commutative
template <class T>
inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int)
{
return python::xincref((T*)p);
}
// this is a borrowed handle which cannot be null, so make sure p is not null
// and increment refcount.
template <class T>
inline T* manage_ptr(detail::borrowed<T>* p, long)
{
return python::incref(expect_non_null((T*)p));
}
// p is not borrowed and can be null - do nothing.
template <class T>
inline T* manage_ptr(null_ok<T>* p, long)
{
return (T*)p;
}
// p is not borrowed and cannot be null - make sure it isn't null indeed.
template <class T>
inline T* manage_ptr(T* p, ...)
{
return expect_non_null(p);
}
null_ok<T>
不需要完成此代码的编译,因此它只是声明,未定义。完成它只会为编译器增加额外的工作。