Реализуйте конкретный метод в универсальном классе - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть вопросы, некоторое время искал в интернете, но ничего хорошего не вышло.

У меня есть универсальный класс Image2D для 2D-изображения:

template <typename TValue>
class Image2D 
{
    public:
    typedef Image2D<TValue>    Self;      // le type de *this
    typedef TValue             Value;     // le type pour la valeur des pixels
    typedef std::vector<Value> Container; // le type pour stocker les valeurs des pixels de l'image.

    Image2D( int w, int h, Value g = Value() )
        : m_width(w), m_height(h), m_data(Container(w * h, g)) { }

    struct Iterator : public Container::iterator 
    {
        Iterator( Self & image, int x, int y ) 
        : Container::iterator( image.m_data.begin() + image.index( x, y ) ) { }
    };
    Iterator begin() 
    { 
        return start( 0, 0 );
    }
    Iterator end()   
    { 
        return start( 0, h() ); 
    }
    Iterator start( int x, int y ) 
    { 
        return Iterator( *this, x, y ); 
    }
...
};

Это позволяет мне выбирать определенные типы пикселей изображения, например, unsigned char или Color(unsigned char, unsigned char, unsigned char), когда я создаю экземпляр этого универсального класса.

Мне нужно добавить метод в этот класс, где реализация может отличаться для определенных типов:

template <typename TValue>
class Image2D
{
...

    template <typename Color>
    void sepiaFilter()
    {
        for(Iterator it = this -> begin(), itE = this -> end(); it != itE; ++it)
        {
            Color oldColor = *it;

            Color newColor = oldColor;

            newColor.red = std::min((oldColor.red * .393) + (oldColor.green * .769) + (oldColor.blue * .189), 255.0);
            newColor.green = std::min((oldColor.red * .349) + (oldColor.green * .686) + (oldColor.blue * .168), 255.0);
            newColor.blue = std::min((oldColor.red * .272) + (oldColor.green * .534) + (oldColor.blue * .131), 255.0);

            *it = newColor;
        }
    }
...
};

То же самое относится к unsigned char, но суть метода не должна быть одинаковой.

Проблема в том, что я не знаю, как специализировать обобщенную функцию для определенных типов. Я пытался создать это:

template<>
class Image2D<Color> 
{
    template <typename Color>
    void sepiaFilter()
    {
        for(Iterator it = this -> begin(), itE = this -> end(); it != itE; ++it)
        {
            Color oldColor = *it;

            Color newColor = oldColor;

            newColor.red = std::min((oldColor.red * .393) + (oldColor.green * .769) + (oldColor.blue * .189), 255.0);
            newColor.green = std::min((oldColor.red * .349) + (oldColor.green * .686) + (oldColor.blue * .168), 255.0);
            newColor.blue = std::min((oldColor.red * .272) + (oldColor.green * .534) + (oldColor.blue * .131), 255.0);

            *it = newColor;
        }
    }
}

И создайте еще один определенный класс Image2D. Но для этого необходимо, чтобы итератор был повторно реализован в этом специализированном классе; поэтому я не могу использовать итератор универсального класса.

Так что ни одно из этих решений не работает, поэтому я прошу помощи ... Heeeeelp!

Как я могу делать то, что хочу?

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Спасибо, ребята, за вашу помощь! Решение Броницки работает. После того, что он сказал, используя

void sepiaFilter() { ... }

было хорошим решением.

Я назвал это с

img.sepiaFilter();

в методе main, img - экземпляр Image2D.

0 голосов
/ 17 ноября 2018

Если я правильно понимаю ваш вопрос, то есть несколько маршрутов, которые вы могли бы выбрать. Я думаю, что вам нужна специализация на шаблонах. Для этого вы хотите изменить универсальный класс, включив в него функцию, которую вы хотите специализировать:

template <typename TValue>
class Image2D{
    //your original code here
    void sepiaFilter(Image2D<Value> img){}
};

Обратите внимание, что я не дал функции тело. Прямо сейчас это ничего не делает. Теперь мы специализируемся на функции:

template<>
void Image2D<Color>::sepiaFilter(Image2D<Color> img){
    //body of your function here
}

И это все! Image2D<Color> теперь имеет специально определенное поведение.

Кроме того, это не было частью вашего вопроса, но слово мудрым на вашем следе для этой функции. Я бы порекомендовал вместо этого использовать

//code before function definition
static void sepiaFilter(Image2D<Value>& img){
    //modify member values of img by reference
}
//code after function definition

static добавлено, потому что функция не изменяет значения членов своего собственного объекта. А амперсанд передает его по ссылке, иначе любые изменения, внесенные вами в img, исчезнут, когда вы закончите. Кроме того, вы можете сделать это:

//code before function definition
void sepiaFilter(){
    //modify member values of this
}
//code after function definition

В этом случае вы хотели бы изменять своих собственных членов, а не членов чего-то переданного

Во всяком случае, я надеюсь, что это ответ на ваш вопрос, и удачи!

...