Search code examples
c++templatesmember-functionsclass-template

How can you specialize a non-template member function of a class template?


Suppose I have the following class:

template <typename T>
class MyClass
{
public:
    void SetValue(const T &value) { m_value = value; }

private:
    T m_value;
};

How can I write a specialized version of the function, for T=float (or any other type)?

Note: A simple overload won't suffice because I only want the function to be available for T=float (i.e. MyClass::SetValue(float) doesn't make any sense in this instance).


Solution

  • template <typename T>
    class MyClass {
    private:
        T m_value;
    
    private:
        template<typename U>
        void doSetValue (const U & value) {
            std::cout << "template called" << std::endl;
            m_value = value;
        }
    
        void doSetValue (float value) {
            std::cout << "float called" << std::endl;
        }
    
    public:
        void SetValue(const T &value) { doSetValue (value); }
    
    };
    

    or (partial template specialization):

    template <typename T>
    class MyClass
    {
    private:
        T m_value;
    
    public:
        void SetValue(const T &value);
    
    };
    
    template<typename T>
    void MyClass<T>::SetValue (const T & value) {
        std::cout << "template called" << std::endl;
        m_value = value;
    }
    
    template<>
    void MyClass<float>::SetValue (const float & value) {
        std::cout << "float called" << std::endl;
    }
    

    or, if you want the functions to have different signatures

    template<typename T>
    class Helper {
    protected:
        T m_value;
        ~Helper () { }
    
    public:
        void SetValue(const T &value) {
            std::cout << "template called" << std::endl;
            m_value = value;
        }
    };
    
    template<>
    class Helper<float> {
    protected:
        float m_value;
        ~Helper () { }
    
    public:
        void SetValue(float value) {
            std::cout << "float called" << std::endl;
        }
    };
    
    template <typename T>
    class MyClass : public Helper<T> {
    };