// интерфейсclass A
{
public:
A();
virtual ~A() = 0;
int GetValueA();
char* GetValueB();
};
// используется полиморфноclass B: public A
{
public:
~B() {}
int GetValueA();
char* GetValueB();
long GetValueC();
... // тут еще может быть стопицот геттеров
};
// всё это в каком то контейнере, для простоты пусть std::vector<A*>.
std::vector<A*> vecA; // здесь данные всегда живы, не удаляются, не изменяются...
Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?
Посмотрел в сторону алгоритмов возвращающие наборы, типа std::copy_if.
int Func(const std::vector<A*>& in, std::vector<A*>& out)
{
out.resize(in.size());
auto it = std::copy_if(in.begin(), in.end(), out.begin(), [&](A* b) -> bool
{
if (b.GetValueA()) return true;
if (b.GetValueB()) return false;
// и т.д., на основании значений геттеров принимаем решение, копировать или нет
});
out.resize(std::distance(out.begin(), it));
}
И так делаем часто, выборку из контейнера по каким то условиям на основании значений геттеров.
Кажется както не эффективно, особенно постоянное копирование.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Вопрос сугубо практический...
МД>
МД>// всё это в каком то контейнере, для простоты пусть std::vector<A*>.
МД>std::vector<A*> vecA; // здесь данные всегда живы, не удаляются, не изменяются...
МД>
МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range? МД>Посмотрел в сторону алгоритмов возвращающие наборы, типа std::copy_if.
МД>И так делаем часто, выборку из контейнера по каким то условиям на основании значений геттеров. МД>Кажется както не эффективно, особенно постоянное копирование.
Копирование вектора указателей в другой вектор по идее очень дешевая операция, так что я бы для начала проверил, что оно реально влияет на производительность. Ещё неплохо бы знать сценарии использования возращаемых выборок.
Т.к. контейнер всегда живой и не меняется, можно возврщать прокси-обертку, с итераторным интерфейсом, например такую:
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Кажется както не эффективно, особенно постоянное копирование.
В go и Rust есть такая штука как slice, в С++ оно вроде не работает для веторов, но можно посомтреть на range наерное, т.е. не нужно копировать ничего просто постмроить нечно на онове праы итераторов начала и конца.
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Вопрос сугубо практический... МД>Есть типа такого: МД>... МД>std::vector<A*> vecA; // здесь данные всегда живы, не удаляются, не изменяются... МД>[/ccode] МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?
Здравствуйте, Мёртвый Даун, Вы писали:
МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?
Думаю, нужно смотреть в сторону Range library. В частности, эта штука:
Здравствуйте, ViTech, Вы писали:
VT>Здравствуйте, Мёртвый Даун, Вы писали:
МД>>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?
VT>Думаю, нужно смотреть в сторону Range library. В частности, эта штука: VT>
2) Еще можно написать кастомный итератор с помощью boost::iterator_facade — это, скорее всего, то же, что и ranges::v3::view::filter, только вид сбоку.
VT>Кстати, кто-нибудь плотно работал с ranges? Возвращать из функции какой-нибудь ranges::view::xxxx это хорошо или плохо ?
Это может не работать, если время жизни объектов, по которым итерируют итераторы (они ведь там внутри генерятся?), будет недостаточно длинным, например. Логично использовать полученный диапазон "на лету", а не хранить его где-то, а поэтому проблем быть не должно, за исключением случаев, когда диапазоны (какие-то их преобразования типа reversed_range) "наслаиваются" и где-то происходит "преждевременная эвакуация" временных объектов.