Search code examples
c++templatestemplate-specializationpartial-specialization

Partial specialisation of member function with non-type parameter


I have a template class with both a type and a non-type template parameter. I want to specialize a member function, what I finding is, as in the example below, I can do a full specialization fine.

template<typename T, int R>
struct foo
{
    foo(const T& v) :
        value_(v)
    {}

    void bar()
    {
        std::cout << "Generic" << std::endl;
        for (int i = 0; i < R; ++i)
            std::cout << value_ << std::endl;
    }

    T value_;
};

template<>
void foo<float, 3>::bar()
{
    std::cout << "Float" << std::endl;
    for (int i = 0; i < 3; ++i)
        std::cout << value_ << std::endl;
}

However this partial specialization won't compile.

template<int R>
void foo<double, R>::bar()
{
    std::cout << "Double" << std::endl;
    for (int i = 0; i < R; ++i)
        std::cout << value_ << std::endl;
}

Is there a way to achieve what I'm attempting would anyone know? I tried this in MSVC 2010.


Solution

  • You can wrap the function inside a class.

    Only classes, not functions, may be partially specialized.

    template<typename T, int R>
    struct foo
    {
        foo(const T& v) :
            value_(v)
        {}
    
        void bar()
        {
            return bar_impl< T, R >::bar( * this );
        }
    
        friend struct bar_impl< T, R >;
    
        T value_;
    };
    
    template< typename T, int R >
    struct bar_impl {
        static void bar( foo< T, R > &t ) {
            std::cout << "Generic" << std::endl;
            for (int i = 0; i < R; ++i)
                std::cout << t.value_ << std::endl;
        }
    };
    
    template<>
    struct bar_impl<float, 3> {
    static void bar( foo< float, 3 > &t ) {
        std::cout << "Float" << std::endl;
        for (int i = 0; i < 3; ++i)
            std::cout << t.value_ << std::endl;
    }
    };
    
    template<int R>
    struct bar_impl<double, R> {
    static void bar( foo< double, R > &t ) {
        std::cout << "Double" << std::endl;
        for (int i = 0; i < R; ++i)
            std::cout << t.value_ << std::endl;
    }
    };