13

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.

Eoin
  • 1,709
  • 11
  • 22

2 Answers2

16

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;
}
};
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • And I'm so glad that's lifted for C++0x. :) – Xeo Apr 16 '11 at 18:10
  • 3
    @Xeo: It isn't :v( . I forget the details, but the function overload resolution and class specialization resolution mechanisms are one and the same, and the two slightly different use-cases don't combine cleanly. – Potatoswatter Apr 16 '11 at 18:15
  • The upshot of all this is that there is no type deduction on the function arguments. – Potatoswatter Apr 16 '11 at 18:21
  • Thanks Potatoswatter, I should be able to achieve exactly what I was aiming for now! – Eoin Apr 16 '11 at 18:54
3

Partial specialization is possible only for the full class, not a member function. So you need

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

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

    double value_;
};
AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • Thanks AProgrammer, didn't realize partial specialization isn't at all possible on a member function. – Eoin Apr 16 '11 at 18:53