Имеем - шаблонная функция, еще и рекурсивная, в которой много чего подтянуто из разных (заголовочных) файлов, а шаблонность только одна - запись найденного значения в итератор. Что-то примерно такое
template<typename Itor>
void terribleFunction(Itor it, type1 param1, type2 param2, ...)
{
// Всякие дела
for(....
{
// И еще дела
// Первое использование it
if(...) terribleFunctiom(it,p1,p2,...);
// И еще...
// Второе использование it
if (...) *it++ = что-то;
// И еще...
}
}
Примерно так. Хочется максимально спрятать весь код - в котором ничего шаблонного - или в библиотеку, или в отдельный файл - вобщем, как минимум постараться не плодить зависимости в заголовочном файле, выписывая в нем весь код, постараться максимально убрать его в какие-нибудь вспомогательные функции, что ли. Но что-то что ни придумываю - все через одно неприличное место...
Какой бы тут хитрый метод применить, намекните?...
Если единственное использование - это X x = expr; *it++ = x;
, то эту операцию можно обернуть в std::function<void(X)> f
, передавать не итератор а эту функцию, использовать как f(x)
.
Либо можно передавать класс с виртуальными функциями.
По сути, все что вам нужно это полиморфное поведение вашего итератора. Сейчас вы достигаете полиморфизма за счет шаблонов. Можно достичь того же эффекта при помощи наследования и виртуальных методов.
Для начала объявим интерфейс итератора:
class IIterator{
public:
virtual void next() = 0;
virtual void setValue(int value) = 0;
virtual int value() const = 0;
virtual ~IIterator(){}
};
Думаю вы знаете тип значения, которое хотите писать в итератор. Для примера я взял int
.
Теперь нам нужна конкретная реализация, причем для всех возможных итераторов. Да, снова шаблоны:
template<class It>
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<typename It>
void terribleFunction(It it){
Iterator<It> iterator(it);
terribleFunctionHelper(iterator);
}
В результате этих нехитрых манипуляций, все зависимости оказались в нешаблонной terribleFunctionHelper
. Можно смело переносить ее код в cpp файл.
Полный пример
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
В каких случаях используются операторы x*ptm или p->*ptm? Прошу привести минимальный пример, где это может понадобиться
ЗдравствуйтеКто знает, почему в этом проэкте две ошибки? "invalid conversion from 'int()(const char)' to 'const void*' [-fpermissive]"
Я создаю вектор ссылок на объекты моего класса в главной функции - всё работает замечательноСоздаю схожий вектор в ином классе - всё работать...