Можно ли сузить дружеские отношения между классами и функциями, когда задействованы несколько типов шаблонов? - PullRequest
2 голосов
/ 06 мая 2009

Предположим, я представляю класс изображения как:

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>&);

внутри определения изображения. Компилятору это (или другие варианты) совсем не нравится, главным образом потому, что он не соответствует исходному объявлению функции, поэтому частный указатель недоступен. Можно ли получить то, что я хочу здесь, или я должен согласиться на «более дружественную» версию?

Ответы [ 2 ]

3 голосов
/ 06 мая 2009

Насколько я знаю, у вас не может быть частично специализированной шаблонной функции.

Вы можете создать Convolver структуру, которую вы можете частично специализировать, а затем создать оболочку для создания свертки.

1 голос
/ 07 мая 2009

Единственный способ увидеть это - определить функцию внутри класса Image, например:

#include <iostream>
using std::cout;

template <typename Pixel>
struct image
{
    template <typename KernelValue>
    friend image<Pixel> convolve(image<Pixel> const&, image<KernelValue> const&)
    {
            cout << "foo\n";
            return image<Pixel>();
    }
};

int main()
{
    image<int> i;
    image<float> i2;

    convolve(i, i2);
}
...