On Jul 28, 2009, at 9:53 PM, Roland Steiner wrote:


I definitely like the general idea, but I don't think a NeverNull template is worth it in the general case, for the following reasons:

First, I don't hink you can catch even a meaningful subset of all cases of NULL assignment at compile time. OTOH, writing a template class that wraps a non-null pointer has its use mainly in order to annotate header files, and to "auto-insert" the ASSERT. In cpp files it's just a cosmetic difference to ASSERTs, and enforcing the use throughout would probably change far too much code, and run into other cumbersome details in addition to the ones I mention below.

Compile time checks are great, and any is better than none -- but even runtime checks are an improvement, especially if you take the logical step of adding a runtime check in _all_ builds. Effectively:
template <typename T> class NeverNull {
    template <typename U> NeverNull(const U* ptr)
        : m_ptr(ptr)
    {
        if (!ptr)
            CRASH();
    }
    template <typename U> NeverNull(NeverNull<U> ptr)
        : m_ptr(ptr.get())
    {
    }

    T* get() { return m_ptr; }
    ...
}

NeverNull->NeverNull assignment circumvents the null check, and assignment of a null pointer immediately crashes, rather than crashing sometime later due to an "impossible" null. That way we can see immediately when the crash is caused (on the assumption that assigning null to a NeverNull _will_ crash eventually, so early crash is best).


OTOH in order to be consequent, one would also need to use NeverNull<X> in return values, e.g.,

NeverNull<foo> bar() const;

Implementing such a function would have to be conscious of the fact that a NeverNull<X> must always be initialized. i.e., you cannot write

NeverNull<foo> Baz::bar() const
{
NeverNull<foo> returnValue;
... compute returnValue ...
return returnValue;
}
Indeed, there should not be a default constructor to a NeverNull

Similar cases may also arise in other cases, when initialization is non-trivial. So either one must us a tailored implementation, or use plain pointers for the main computation. Both are somewhat defeating the purpose, since they cause additional overhead.

Second, I believe that even if NeverNull<X> is a POD class, such wrapping classes tend to defeat some compiler optimizations that would be performed on raw pointers otherwise, so I'd be surprised to not see any performance degradations. Whether or not they are significant, I can't say.

The primary win for NeverNull is for members that will always be non- null so any attempt to assign null is unsafe, and so that you don't find yourself asking "can this be null?" all the time. I suspect overall NeverNull would likely reduce the number of null checks in the code base.

- Roland

--Oliver

_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev

Reply via email to