Есть некий класс, назовем его foo, который унаследован от boost::enable_shared_from_this<> и активно использует shared_from_this() внутри своего кода.
Соответственно есть typedef boost::shared_ptr<foo> foo_ptr;
Хочется следующего:
foo_ptr my_ptr = some_class::get_foo_ptr();
int i = my_ptr[10]; // здесь работает перегруженный оператор [] класса foo, точнее shared_ptr перадресует на него.
Понятно что есть несколько путей решения данной задачи, но хотелось бы максимально сохранить совместимость с shared_ptr и не изобретать велосипедов в виде самописных умных указателей. Ну и полностью копипасть shared_ptr (даже специализируя его для foo) тоже как-то не хочется.
Здравствуйте, szag, Вы писали:
S>Посовейте, как лучше поступить?
Если уж говорить про лучше, то имхо вам не следует менять семантику оператора [] при использовании с указателями, которую shared_ptr в точности повторяет.
Я бы предложил рассмотреть создание какого-либо get-метода в вашем классе foo и возложить на него вашего перегруженного оператора.
Если совсем невмоготу использовать operator[], почему бы просто не разименовывать указатель перед "индексацией"
Здравствуйте, BogusCoder, Вы писали:
BC>Если уж говорить про лучше, то имхо вам не следует менять семантику оператора [] при использовании с указателями, которую shared_ptr в точности повторяет.
Именно так сейчас это и работает, но это стало неудобным, так как приходится писать конструкции вида my_ptr->get_somethings("some_name"); вместо my_ptr["some_name"]. Дело в том, что по смыслу там этот оператор [] тоже хорошо вписывается т.к. для пользователя класс foo это своего рода контейнер и доставать из него элементы приходится часто в коде.
BC>Я бы предложил рассмотреть создание какого-либо get-метода в вашем классе foo и возложить на него вашего перегруженного оператора. BC>Если совсем невмоготу использовать operator[], почему бы просто не разименовывать указатель перед "индексацией"
Приведу пример:
A a;
a.push(my_ptr->get_something("some_name1"), my_ptr->get_something("some_name2"), my_ptr->get_something("some_name1"));
a.push((*my_ptr)["some_name1"], (*my_ptr)["some_name1"], (*my_ptr)["some_name1"]); // Конечно можно и так
a.push(my_ptr->f("some_name1"), my_ptr->f("some_name2"), my_ptr->f("some_name1")); // или даже так
a.push(my_ptr["some_name1"], my_ptr["some_name1"], my_ptr["some_name1"]); // но хочется вот так, так удобнее и короче, а перечислений этих "some_name" в коде обычно пара десятков
К тому же оператор [] не единственный, который хотелось бы перегрузить
A a;
DataAccessor d(my_ptr);
a.push(d["some_name1"], d["some_name1"], d["some_name1"]);
разделйте ответственности и не мешайте все в кучу
S>К тому же оператор [] не единственный, который хотелось бы перегрузить
реализуйте эти идеи через класс DataAccessor
Здравствуйте, uzhas, Вы писали:
U>реализуйте эти идеи через класс DataAccessor
В общем случае наверное да, но в моём это слишком не удобно. Обычно в одном скопе используется 3-5 экземпляров foo_ptr, прибавить к этому еще 3-5 DataAccesser'ов это увеличит код и усложнит его читабельность. А пользователю надо будет знать семантику не только foo_ptr но и семантику его DataAccesser.
В общем, похоже, придется писать свой смарт поинтер boost::shared_ptr based.
Здравствуйте, szag, Вы писали:
U>>реализуйте эти идеи через класс DataAccessor
S>В общем случае наверное да, но в моём это слишком не удобно. Обычно в одном скопе используется 3-5 экземпляров foo_ptr, прибавить к этому еще 3-5 DataAccesser'ов это увеличит код и усложнит его читабельность. А пользователю надо будет знать семантику не только foo_ptr но и семантику его DataAccesser.
Вместо DataAccessor можно взять const T&, где T — тот тип, на который ptr. А читабельность кода гораздо больше ухудшит перегрузка [] для указателей.