Алгоритмы возвращающие наборы, или...
От: Мёртвый Даун Россия  
Дата: 07.06.18 02:33
Оценка:
Вопрос сугубо практический...

Есть типа такого:

// интерфейс
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));
}


И так делаем часто, выборку из контейнера по каким то условиям на основании значений геттеров.

Кажется както не эффективно, особенно постоянное копирование.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re: Алгоритмы возвращающие наборы, или...
От: XuMuK Россия  
Дата: 07.06.18 08:38
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Вопрос сугубо практический...


МД>
МД>// всё это в каком то контейнере, для простоты пусть std::vector<A*>.
МД>std::vector<A*> vecA; // здесь данные всегда живы, не удаляются, не изменяются...
МД>


МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?

МД>Посмотрел в сторону алгоритмов возвращающие наборы, типа std::copy_if.

МД>И так делаем часто, выборку из контейнера по каким то условиям на основании значений геттеров.

МД>Кажется както не эффективно, особенно постоянное копирование.

Копирование вектора указателей в другой вектор по идее очень дешевая операция, так что я бы для начала проверил, что оно реально влияет на производительность. Ещё неплохо бы знать сценарии использования возращаемых выборок.
Т.к. контейнер всегда живой и не меняется, можно возврщать прокси-обертку, с итераторным интерфейсом, например такую:

struct Selection {
  Selection(std::vector<A*>&, std::function<bool(A*)> predicate);
  std::vector<A*>::iterator begin() const;
  std::vector<A*>::iterator end() const;
}
Re: Алгоритмы возвращающие наборы, или...
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 07.06.18 09:47
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Кажется както не эффективно, особенно постоянное копирование.

В go и Rust есть такая штука как slice, в С++ оно вроде не работает для веторов, но можно посомтреть на range наерное, т.е. не нужно копировать ничего просто постмроить нечно на онове праы итераторов начала и конца.
Sic luceat lux!
Re: Алгоритмы возвращающие наборы, или...
От: Skorodum Россия  
Дата: 07.06.18 11:08
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Вопрос сугубо практический...

МД>Есть типа такого:
МД>...
МД>std::vector<A*> vecA; // здесь данные всегда живы, не удаляются, не изменяются...
МД>[/ccode]
МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?

forward iterator, как regex_token_iterator

Если нужно сохранять найденные объекты, то можно как-то так:

// sorted set is needed for intersection
set<string> sorted_unique_tokens(const string &input, const string &regex)
{
    // passing -1 as the submatch index parameter performs splitting
    std::regex re(regex);
    sregex_token_iterator first{input.begin(), input.end(), re, -1};
    sregex_token_iterator last;
    return {first, last};
}
Re: Алгоритмы возвращающие наборы, или...
От: ViTech  
Дата: 13.06.18 09:07
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?


Думаю, нужно смотреть в сторону Range library. В частности, эта штука:
struct Selection {
  Selection(std::vector<A*>&, std::function<bool(A*)> predicate);
  std::vector<A*>::iterator begin() const;
  std::vector<A*>::iterator end() const;
}
очень похожа на ranges::view::filter. Стало быть, возвращать надо либо новый контейнер, либо ranges::view::xxxx.

Кстати, кто-нибудь плотно работал с ranges? Возвращать из функции какой-нибудь ranges::view::xxxx это хорошо или плохо ?
Пока сам не сделаешь...
Re[2]: Алгоритмы возвращающие наборы, или...
От: Warturtle  
Дата: 19.06.18 12:30
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Здравствуйте, Мёртвый Даун, Вы писали:


МД>>Хочется функцию, которая будет обращаться к этому контейнеру, и на основании значений возвращаемых геттерами объектов класса B, чтото возвращала. Но что? Набор? Новый std::vector? Range?


VT>Думаю, нужно смотреть в сторону Range library. В частности, эта штука:

VT>
struct Selection {
VT>  Selection(std::vector<A*>&, std::function<bool(A*)> predicate);
VT>  std::vector<A*>::iterator begin() const;
VT>  std::vector<A*>::iterator end() const;
VT>}
очень похожа на ranges::view::filter. Стало быть, возвращать надо либо новый контейнер, либо ranges::view::xxxx.


1) Или не возвращать ничего, а передать доп параметр, который будет делать необходимое:
template< class RangeT >
void ProcessSelection(RangeT & rng, std::function< bool(typename RangeT::value_type)> pred, std::function< void(typename RangeT::value_type) > const & action)
{
    ...
    if (pred(a))
        action(a);
    ...
}


2) Еще можно написать кастомный итератор с помощью boost::iterator_facade — это, скорее всего, то же, что и ranges::v3::view::filter, только вид сбоку.

VT>Кстати, кто-нибудь плотно работал с ranges? Возвращать из функции какой-нибудь ranges::view::xxxx это хорошо или плохо ?


Это может не работать, если время жизни объектов, по которым итерируют итераторы (они ведь там внутри генерятся?), будет недостаточно длинным, например. Логично использовать полученный диапазон "на лету", а не хранить его где-то, а поэтому проблем быть не должно, за исключением случаев, когда диапазоны (какие-то их преобразования типа reversed_range) "наслаиваются" и где-то происходит "преждевременная эвакуация" временных объектов.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.