Как удалить элементы из вектора на основе записей в другом векторе? - PullRequest
0 голосов
/ 01 ноября 2018

Я искал stackoverflow и уже нашел частичный ответ на мой вопрос: Как удалить элементы из вектора на основе условия в другом векторе? В моем случае у меня есть два вектора, один из которых содержит целые числа, а другой содержит общие указатели (std :: shared_ptr ), и я не могу вычислить арифметику указателя, чтобы получить работающий код.

class someAbstractClass
{     
};

class someClass : public someAbstractClass
{
};    

std::vector<int> condition;
std::vector<std::shared_ptr< someAbstractClass >> container;

condition.push_back(0);
condition.push_back(1);
condition.push_back(0);

container.push_back( std::make_shared< someClass > );
container.push_back( std::make_shared< someClass > );
container.push_back( std::make_shared< someClass > );

std::erase( std::remove_if( container.begin(), conatiner.end(),
           [&] ( const std::shared_ptr< someAbstractClass > &s ) 
           { 
               return condition[ &s - &(*container.begin()) ] == 1;
           } ), container.end() );

Есть ли способ заставить эту работу?

1 Ответ

0 голосов
/ 01 ноября 2018

Вы сравниваете shared_ptr объекты друг с другом. Вместо этого вам нужно сравнить адреса этих объектов. И лямбда-выражение должно принимать входной аргумент ссылка , чтобы убедиться, что он работает с адресом исходного объекта в векторе, а не с копией объекта в другом месте в памяти.

container.erase(
    std::remove_if(
        container.begin(), container.end(),
        [&](const std::shared_ptr<someType> &s) {
            return condition[ &s - &(*container.begin()) ] == 1;
        }
    ),
    container.end()
);

Демонстрационная версия

Сравните это со следующим фрагментом в принятом ответе с на вопрос , на который вы ссылались:

a.erase(remove_if(begin(a), end(a),
    [b&](const myClass& d) { return b[&d - &*begin(a)].alive(); }),
    end(a));

Видите сходство?

Вычитание напечатанных адресов двух допустимых элементов в контейнере из последовательной памяти, подобно std::vector, создает смещение между двумя элементами. И когда нижний адрес предназначен для 1-го элемента контейнера, это смещение фактически совпадает с индексом более высокого адреса. Таким образом, арифметика указателей в этом примере может получить индекс лямбда-аргумента в пределах condition (при условии, что condition имеет по крайней мере столько же элементов, сколько container).

...