Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > контейнер, функтор и шаблоны


Автор: zss 3.3.2006, 09:59
подскажите пожалуйста можно ли так сделать

есть функтор
Код

template <class T>
struct Destroyer {
    void operator () (T*& object) const {
        if (!object) return;
        delete object;
        object = NULL;
    }
};


он используется для удаления объектов, указатели которых
храняться в контейнере (любом)

хочется для контейнера создать функцию, которая убивала бы
объекты по необходимости (в зависимости от функтора)

что-то вроде
Код

template <typename T, class Container = std::vector<T> >
void DestroyContainer<T, Container > (Container<T>& container) {

    std::for_each (container.begin(), container.end(), Destroyer <T> ());
    connections_.erase (
        std::remove (container.begin(), container.end(), (T *)NULL),
        container.end()
    );
}



только хотелось бы еще и сам функтор задавать шаблонами
Тоесть чтоб функция работала для любого контейнера с заданным функтором

Автор: Daevaorn 3.3.2006, 10:35
zss,
Если в первом коде вроде всё нормально, то во втором куча проблем.

1. template <typename T, class Container = std::vector<T> > - спрашивается зачем дефолтить шаблонный параметр, да ещё и вектором. Не надо!

2. void DestroyContainer<T, Container > (Container<T>& container) { - зачем после имени функции опять перечислять шаблонные параметры? Не надо, шаблонные функции всё равно нельзя специализировать!

3. template <typename T, class Container, class Func > - тогда в коде пишешь std::for_each (container.begin(), container.end(), Func() ); и получаешь совсем обощённый механизм. Но тогда меняй название.

4. connections_.erase (
std::remove (container.begin(), container.end(), (T *)NULL),
container.end()
);

ну вот тут тоже не всё понятно, чего ты хочешь если у тебя функтор удаляет все элементы. Может просто clear() вызвать?

Автор: zss 3.3.2006, 10:41
Цитата(Daevaorn @ 3.3.2006, 10:35 Найти цитируемый пост)
спрашивается зачем дефолтить шаблонный параметр, да ещё и вектором. Не надо!

а чем это плохо ?

Цитата(Daevaorn @ 3.3.2006, 10:35 Найти цитируемый пост)
Не надо, шаблонные функции всё равно нельзя специализировать!

если не ошибаюсь - нельзя частично специализировать

Цитата(Daevaorn @ 3.3.2006, 10:35 Найти цитируемый пост)
ну вот тут тоже не всё понятно, чего ты хочешь если у тебя функтор удаляет все элементы. Может просто clear() вызвать?

это этот функтор все удаляет.
А если я подсуну функтор, который будет дергать методы класса и
в зависимости от результата решать - удалять или нет

для этого я и хочу функтор задавать шаблонно

Автор: Daevaorn 3.3.2006, 10:52
Цитата(zss @ 3.3.2006, 11:41 Найти цитируемый пост)
а чем это плохо ?

А чем это хорошо? Что тебе это дает? Боюсь, что совсем ничего.

Цитата(zss @ 3.3.2006, 11:41 Найти цитируемый пост)
если не ошибаюсь - нельзя частично специализировать

Да. Но это не меняет сути, зачем потом писать параметры опять?

Цитата(zss @ 3.3.2006, 11:41 Найти цитируемый пост)
это этот функтор все удаляет.
А если я подсуну функтор, который будет дергать методы класса и
в зависимости от результата решать - удалять или нет

Я именно твоего данный код имел ввиду.

Автор: zss 3.3.2006, 11:11
Цитата(Daevaorn @ 3.3.2006, 10:52 Найти цитируемый пост)
А чем это хорошо? Что тебе это дает? Боюсь, что совсем ничего.

меньше писать smile


Цитата(Daevaorn @ 3.3.2006, 10:52 Найти цитируемый пост)
Да. Но это не меняет сути, зачем потом писать параметры опять?

согласен - аналогично моему ответу выше smile

Daevaorn, только немного не понятно почему
Код

template <typename T, class Container, class Func >


не понятно, что Container и Func зависят от T

я думал что будет что-то вроде
Код

template <template <class T> class Container, class Func >


только Func опять не зависит от T

Автор: Daevaorn 3.3.2006, 11:24
zss,
Если брать твой первоначальный код, то параметр T тебе был нужен лишь для того, тобы создать функтор. Но когда у тебя уже функтор как паремтр шаблона, то можно отказаться и от T. Он не нужен. Всё работу по этому поводу будет выполнять клиентский код, который в зависимости от ситуации будет сам выбирать парметры для функтора.
И ещё, допустим, у вектора и один шаблонный параметр (ну если уже совсем быть точным, то только обязательный один), но это не значит, что у всех других контейнеров тоже самое. Так, что твой вариант ещё теряет обобщенность smile

Автор: zss 3.3.2006, 13:08
Daevaorn, довольно убедительно - принимается

только хотелось бы для общего развития (и так сказать для закрепления)
увидеть еще варианты (желательно с параметрами по-умолчанию)

Автор: Chaos A.D. 3.3.2006, 15:35
Я бы сделал так:
Код

template <class Iterator, class Functor>
void ApplyAndRemove( Iterator begin, Iterator end, Functor func )
{
    std::for_each(begin, end, func);
    std::erase( std::remove( begin, end, NULL ), end );
}


Это, ИМХО, как-то больше в стиле STL - функция работает с последовательностью.
По-моему, так более гибко.

Автор: zss 3.3.2006, 15:45
Chaos A.D., а если итератор становится недействительным ?


P.S.
Daevaorn, твой код не хочет собираться
Код

template <typename T, class Container, class Functor >
void DestroyContainer (Container& container) {

    std::for_each (container.begin(), container.end(), Functor <T> ());
    connections_.erase (
        std::remove (container.begin(), container.end(), (T *)NULL),
        container.end()
    );
}

//тогда

std::vector<MyClass> myClass;
DectroyContainer <MyClass, std::vector<MyClass *>, Destroyer> (myClass);

Автор: Chaos A.D. 3.3.2006, 16:08
Я прогнал, erase это же функция-член контейнера...

Автор: Daevaorn 3.3.2006, 16:26
zss,
Было бы странно, если это у тебя бы скомпилировалось.

Вот, как вариант:
Код

template <class T>
struct Destroyer
{
    void operator ()( T*& object )const
    {
        if (!object) return;
        delete object;
        object = NULL;
    }
};


template < class Container, class Functor >
void DestroyContainer(Container& container ) 
{
    std::for_each( container.begin(), container.end(), Functor() );
    container.erase (
        std::remove (container.begin(), container.end(), (Container::value_type)0 ),
        container.end()
    );
}


typedef std::vector<MyClass*> MyVector;
MyVectormyClass;

DestroyContainer< MyVector, Destroyer<MyClass> >( myClass );

Автор: zss 3.3.2006, 17:46
Daevaorn, а что я сейчас не так делаю

Код

template <class T>
struct Destroyer : public std::unary_function <T, bool> {

    bool operator () (T*& object) const {
        if (!T->SomeMethod()) return false;
        delete object;
        object = NULL;
        return true;
    }
};

template <class Container, class Functor>
void DestroyContainer (Container& container){

    container.erase (
            std::remove_if (container.begin(), container.end(),    Functor()),
            container.end()
    );
}

template <class T>
class SomeClass{
private :
    typedef std::vector<T*> MyVector;
    MyVector myClass;
public:
    virtual ~SomeClass (){
        DestroyContainer< MyVector, Destroyer<T> >( myClass );    
    }

}


ругается на строку
Код

if (!T->SomeMethod()) return false;


Почему ?

Автор: Daevaorn 3.3.2006, 17:49
zss, Ты это серьезно?smile

if (!T->SomeMethod()) return false;

Т это у тебя что? Правильно, тип. Тогда как ты у типа можешь вызвать не статический метод, да ещё и оператором ->? Никак. Значит пиши object вместо T smile

Автор: zss 3.3.2006, 17:52
Цитата(Daevaorn @ 3.3.2006, 17:49 Найти цитируемый пост)
Т это у тебя что? Правильно, тип. Тогда как ты у типа можешь вызвать не статический метод, да ещё и оператором ->? Никак. Значит пиши object вместо T

блин - все, приехали smile (суши весла smilesmilesmile)


Daevaorn, большое тебе человеческое ...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)