Re: Удаление из контейнера внешеполиморфных объектов
От: Кодт Россия  
Дата: 25.09.09 09:09
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Через внешний полиморфизм в контейнер помещаются объекты разных типов. Необходимо обеспечить возможность удаления из контейнера, зная исходный объект. Пока единственное, что смог придумать — использовать void *. Нет ли элегантного решения?


Что-то в твоём коде не видно void*.
Может быть, ты имел в виду vector< shared_ptr<void> > с очевидной проблемой — что вообще можно делать с такими указателями, кроме удаления и кастинга?

А так, в принципе, нормальное решение.
Единственный момент — это как организовывать интерфейс
— на абстрактном базовом классе и шаблонном наследнике (твой подход)
— на таблицах функций в каждом экземпляре
— — рукодельных
— — стандартных
// using namespace boost или std::tr1 - по вкусу

///////////////////////
// нам нужна только foo

// нет смысла делать шаблон со специализациями, достаточно перегрузить
function<void()> getfoo(pure1* p) { return bind(&pure1::foo1, p); }
function<void()> getfoo(pure2* p) { return bind(&pure2::foo2, p); }


pure1 v1;
pure2 v2;
pure3 v3;
vector<function<void()> doers;
doers.push_back(getfoo(&v1));
doers.push_back(getfoo(&v2));
doers.push_back(bind(&pure3::foo123, &v3, 1, 2, 3)); // можно и руками собрать
doers[2](); // v3.foo3(1,2,3);


//////////////////////////
// нам нужен букет функций

// структура с именованными полями
struct funs
{
    function<void()> foo;
    function<int(int)> bar;
    function<int(int,int)> buz;
};

funs getfuns(pure1* p)
{
    funs fs;
    fs.foo = bind(&pure1::foo1, p);
    fs.bar = bind(&pure1::bar1, p, _1);
    fs.buz = bind(&pure1::buz1, p, _1, _2);
    return fs;
}

vector<funs> doers;
doers.push_back(getfuns(&v1));
doers[0].buz(1,2); // v1.buz1(1,2)

// или кортеж
enum { FOO, BAR, BUZ };
typedef tuple< function<void()>, function<int(int)>, function<int(int,int)> > funset;
// если функций всего две, можно взять не tuple, а pair

funset getfunset(pure1* p)
{
    return make_tuple(
        bind(&pure1::foo1,p),
        bind(&pure1::bar1,p,_1),
        bind(&pure1::buz1,p,_1,_2)
        );
}

vector<funset> doers;
doers.push_back(getfunset(&v1);
doers[0].get<BAR>()(1); // v1.bar1(1)

Кстати, вместо голых указателей можно использовать и умные. Для общности.
function<void()> getfoo(shared_ptr<pure1> p) { return bind(&pure1::foo1, p); }

void nodelete(void*) {}

pure1 v1;
function<void()> f1 = getfoo(shared_ptr<pure1>(v1,nodelete)); // с этой функцией надо быть аккуратнее - она валидна, пока жив v1
function<void()> f2 = getfoo(shared_ptr<pure1>(new pure1)); // а с этой можно делать что угодно
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.