Suppose I represent an image class as:
template <typename Pixel> class Image { ... };
I would need my own swap function to prevent extra copying of images, so I would need to make it a friend of Image. If inside Image I write:
template <typename T> friend void swap(Image<T>&, Image<T>&);
I get what I want, but it makes all swap functions friends of all Image classes. So I can narrow the friend relationship as follows:
template <typename Pixel> class Image;
template <typename T> void swap(Image<T>&, Image<T>&);
template <typename Pixel> class Image {
...
friend void swap<>(Image&, Image&);
};
as described in C++ FAQ-lite 35.16.
Now suppose I also have a convolution function that can take floating-point or integral kernels:
template <typename Pixel, typename KernelValue>
Image<Pixel> convolve(const Image<Pixel>&, const Kernel<KernelValue>&);
Convolution needs access to Image's raw memory, so it too must be a friend. However, I would like to partially narrow the friendship so that convolve is a friend for all KernelValues but only the particular Pixel type, something like:
template <typename KernelValue> friend Image<Pixel>
convolve(const Image<Pixel>&, const Kernel<KernelValue>&);
inside the Image definition. The compiler does not like this (or other variants) at all, mainly because it doesn't match the original function declaration, so the private pointer can't be accessed. Is it possible to get what I want here, or should I settle for the "more friendly" version?