#cpp #проектирование #шаблоны_с++ #рефакторинг
Имеем - шаблонная функция, еще и рекурсивная, в которой много чего подтянуто из разных (заголовочных) файлов, а шаблонность только одна - запись найденного значения в итератор. Что-то примерно такое templatevoid terribleFunction(Itor it, type1 param1, type2 param2, ...) { // Всякие дела for(.... { // И еще дела // Первое использование it if(...) terribleFunctiom(it,p1,p2,...); // И еще... // Второе использование it if (...) *it++ = что-то; // И еще... } } Примерно так. Хочется максимально спрятать весь код - в котором ничего шаблонного - или в библиотеку, или в отдельный файл - вобщем, как минимум постараться не плодить зависимости в заголовочном файле, выписывая в нем весь код, постараться максимально убрать его в какие-нибудь вспомогательные функции, что ли. Но что-то что ни придумываю - все через одно неприличное место... Какой бы тут хитрый метод применить, намекните?...
Ответы
Ответ 1
Если единственное использование - это X x = expr; *it++ = x;, то эту операцию можно обернуть в std::functionf, передавать не итератор а эту функцию, использовать как f(x). Либо можно передавать класс с виртуальными функциями. Ответ 2
По сути, все что вам нужно это полиморфное поведение вашего итератора. Сейчас вы достигаете полиморфизма за счет шаблонов. Можно достичь того же эффекта при помощи наследования и виртуальных методов. Для начала объявим интерфейс итератора: class IIterator{ public: virtual void next() = 0; virtual void setValue(int value) = 0; virtual int value() const = 0; virtual ~IIterator(){} }; Думаю вы знаете тип значения, которое хотите писать в итератор. Для примера я взял int. Теперь нам нужна конкретная реализация, причем для всех возможных итераторов. Да, снова шаблоны: templateclass 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 файл. Полный пример
Комментариев нет:
Отправить комментарий