Search code examples
c++pointerstemplatesdereference

How to delete a member function (full) specialization when writing that specialization is syntactically illegal?


I'm writing a pointer class and have naturally defined the dereference operator as a member function. However, if this type is now void, I need to delete that function because you can't dereference a void pointer. But writing out that specialization itself is a syntax error:

// in ptr.h
template<typename T>
class ptr {
    public:
        T& operator * () const;
};


//in ptr.cpp
template<>
void& ptr<void>::operator * () const = delete;

So how can I implement this? To fix the syntax error, I have to make a syntax error?

I've tried looking in the source code for the std::unique_ptr class but I really can't make sense of that code tbh


Solution

  • You can't separate a template's declarations and implementations between header and cpp files like you are attempting to do:

    Why can templates only be implemented in the header file?

    In any case, you can't specialize just one method of a template class. You have to specialize the entire template, eg:

    template<typename T>
    class ptr {
        public:
            T& operator * () const;
    };
    
    template<>
    class ptr<void> {
        public:
            // simply omit operator* altogether, since void& is illegal...
            //void& operator * () const = delete;
    };
    

    Live Demo

    Otherwise, you can use SFINAE to omit the operator when T=void, eg:

    #include <type_traits>
    
    template<typename T>
    class ptr {
        public:
            template<typename U = T>
            typename
                std::enable_if<!std::is_same<U, void>::value, U&>::type
            operator * () const;
    };
    

    Live Demo