Предположим, я представляю класс изображения как:
template <typename Pixel> class Image { ... };
Мне понадобится своя собственная функция подкачки, чтобы предотвратить дополнительное копирование изображений, поэтому мне нужно сделать ее другом Image. Если внутри изображения я пишу:
template <typename T> friend void swap(Image<T>&, Image<T>&);
Я получаю то, что хочу, но это делает все функции подкачки друзьями всех классов Image. Поэтому я могу сузить отношения с друзьями следующим образом:
template <typename Pixel> class Image;
template <typename T> void swap(Image<T>&, Image<T>&);
template <typename Pixel> class Image {
...
friend void swap<>(Image&, Image&);
};
как описано в C ++ FAQ-lite 35.16 .
Теперь предположим, что у меня также есть функция свертки, которая может принимать ядра с плавающей запятой или целые:
template <typename Pixel, typename KernelValue>
Image<Pixel> convolve(const Image<Pixel>&, const Kernel<KernelValue>&);
Для свёртки нужен доступ к необработанной памяти Image, поэтому он тоже должен быть другом. Тем не менее, я хотел бы частично сузить дружбу, чтобы Convolve был другом для всех KernelValues, но только для определенного типа пикселей, что-то вроде:
template <typename KernelValue> friend Image<Pixel>
convolve(const Image<Pixel>&, const Kernel<KernelValue>&);
внутри определения изображения. Компилятору это (или другие варианты) совсем не нравится, главным образом потому, что он не соответствует исходному объявлению функции, поэтому частный указатель недоступен. Можно ли получить то, что я хочу здесь, или я должен согласиться на «более дружественную» версию?