Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

Как выделить шаблонность из функции?

#cpp #проектирование #шаблоны_с++ #рефакторинг


Имеем - шаблонная функция, еще и рекурсивная, в которой много чего подтянуто из разных
(заголовочных) файлов, а шаблонность только одна - запись найденного значения в итератор.
Что-то примерно такое

template
void terribleFunction(Itor it, type1 param1, type2 param2, ...)
{
    // Всякие дела
    for(....
    {
        // И еще дела

        // Первое использование it
        if(...) terribleFunctiom(it,p1,p2,...);
        // И еще...

        // Второе использование it
        if (...) *it++ = что-то;  

        // И еще...
    }
}


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

Какой бы тут хитрый метод применить, намекните?...
    


Ответы

Ответ 1



Если единственное использование - это X x = expr; *it++ = x;, то эту операцию можно обернуть в std::function f, передавать не итератор а эту функцию, использовать как f(x). Либо можно передавать класс с виртуальными функциями.

Ответ 2



По сути, все что вам нужно это полиморфное поведение вашего итератора. Сейчас вы достигаете полиморфизма за счет шаблонов. Можно достичь того же эффекта при помощи наследования и виртуальных методов. Для начала объявим интерфейс итератора: class IIterator{ public: virtual void next() = 0; virtual void setValue(int value) = 0; virtual int value() const = 0; virtual ~IIterator(){} }; Думаю вы знаете тип значения, которое хотите писать в итератор. Для примера я взял int. Теперь нам нужна конкретная реализация, причем для всех возможных итераторов. Да, снова шаблоны: template class Iterator : public IIterator{ It _iterator; public: explicit Iterator(const It &iterator): _iterator(iterator) {} void next(){ ++_iterator; } void setValue(int value){ *_iterator = value; } int value() const{ return *_iterator; } }; Теперь возьмем весь код из void terribleFunction(Itor it), перенесем его в функцию void terribleFunctionHelper(IIterator &it), и внесем некоторые изменения в использование итераторов: void terribleFunctionHelper(IIterator &it){ //... it.next(); //Раньше тут было ++it; it.setValue(42); //Раньше тут было *it = 42; //... } Код void terribleFunction(Itor it) теперь станет таким: template void terribleFunction(It it){ Iterator iterator(it); terribleFunctionHelper(iterator); } В результате этих нехитрых манипуляций, все зависимости оказались в нешаблонной terribleFunctionHelper. Можно смело переносить ее код в cpp файл. Полный пример

Комментариев нет:

Отправить комментарий