views:

306

answers:

3

I'm trying to use partial template specialization on a (non-member) function, and I'm tripping up on the syntax. I've searched StackOverflow for other partial template specialization questions, but those deal with partial specialization of a class or member function template.

For a starting point, I have:

struct RGBA {
    RGBA(uint8 red, uint8 green, uint8 blue, uint8 alpha = 255) :
        r(red), g(green), b(blue), a(alpha)
    {}

    uint8 r, g, b, a;
};

struct Grayscale {
    Grayscale(uint8 intensity) : value(intensity) {}

    uint8 value;
};

inline uint8 IntensityFromRGB(uint8 r, uint8 g, uint8 b) {
    return static_cast<uint8>(0.30*r + 0.59*g + 0.11*b);
}

// Generic pixel conversion.  Must specialize this template for specific
// conversions.
template <typename InType, typename OutType>
OutType ConvertPixel(InType source);

I can do a complete specialization of ConvertPixel to make an RGBA to Grayscale conversion function like this:

template <>
Grayscale ConvertPixel<RGBA, Grayscale>(RGBA source) {
    return Grayscale(IntensityFromRGB(source.r, source.g, source.b));
}

I'll conceivably have more pixel types that offer red, green, and blue, but perhaps in a different format, so what I'd really like to do is a partial specialization by specifying Grayscale for OutType and still allow for a variety of InTypes. I've tried a variety of approaches like this:

template <typename InType>
Grayscale ConvertPixel<InType, Grayscale>(InType source) {
    return Grayscale(IntensityFromRGB(source.r, source.g, source.b));
}

But the (Microsoft VS 2008 C++) compiler rejects it.

Is what I'm attempting possible? If so, what's the right syntax?

+5  A: 

C++ does not allow partial specialization of function templates.

It doesn't even allow partial specialization of member function templates. When you define a function which is part of a partial specialization of a class template, that might look a bit like you've partially specialized the member function. But you haven't.

Herb Sutter discusses partial specialization

Steve Jessop
Thanks for the link!
Adrian McCarthy
+2  A: 

Partial specialization is a concept that only applies to classes, not free functions or member functions. What you probably want to do is just provide function (or member function) overloads, which sort of map to what partial and full specializations do for classes.

Terry Mahaffey
+4  A: 

It is possible using class partitial specialization:

template<class A, class B>
struct Functor {
    static A convert(B source);
};

template<class B>
struct Functor<GrayScale, B> {
    static GrayScale convert(B source) {
         return Grayscale(IntensityFromRGB(source.r, source.g, source.b));
    }
};

// Common function
template<class A, class B>
A Convert(B source) {
   return typename Functor<A,B>::convert(source);
}
Alexey Malistov
Excellent. Thank you!
Adrian McCarthy