Здравствуйте, <Аноним>, Вы писали:
А>Через внешний полиморфизм в контейнер помещаются объекты разных типов. Необходимо обеспечить возможность удаления из контейнера, зная исходный объект. Пока единственное, что смог придумать — использовать 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>>