Дизайн относительно удалений std :: reference_wrapper - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь использовать std::reference_wrapper для всех элементов другого вектора.Но когда я удаляю исходный элемент, я хочу автоматически удалить элемент в векторе ссылок.Я сделал несколько обходных путей, но они безобразны.Есть предложения?

#include <iostream>
#include <list>

struct A
{
    A(int x) : x(x){}
    int x;
};
std::list<std::reference_wrapper<A>> listRef;

struct B
{
    std::list<A> l;
    B()
    {
        l.emplace_back(42);
        listRef.emplace_back(l.back());
    }
    void foo()
    {
        customRemove(l.back());
    }
    void customRemove(const A & obj)
    {
        //l.remove(obj); // Error: binary '==': no operator found which takes 
        //a left-hand operand of type 'A' (or there is no acceptable conversion)
        // so I did
        l.remove_if([&](const A & obj2) { return &obj == &obj2; });
        // is there a way to automatically remove dangling references?
        listRef.remove_if([&](const A & obj2) { return &obj == &obj2; });
    }
};

int main()
{
    B b;
    std::cout << listRef.size() << '\t' << b.l.size() << '\n'; // prints 1  1
    b.foo();
    std::cout << listRef.size() << '\t' << b.l.size() << '\n'; // prints 0  0
}

1 Ответ

0 голосов
/ 21 сентября 2018

Короче: не делай этого.Нет никакого преимущества в хранении std::reference_wrapper<A> в вашем списке по сравнению с наличием списка необработанных указателей.

Лучшим подходом было бы сохранить std::shared_ptr в l, а затем std::weak_ptr в listRef,Затем, если вы получите висячие ссылки в listRef, вы можете проверить, существует ли объект до того, как его использовать:

std::list<std::weak_ptr<A>> listRef;

struct B
{
    std::list<std::shared_ptr<A>> l;
    B()
    {
        l.emplace_back(new A(42));
        listRef.emplace_back(l.back());
    }
    void foo()
    {
        customRemove(l.back());
    }
    void customRemove(std::shared_ptr< A > obj)
    {
        l.remove(obj);
        obj.reset();
        listRef.remove_if([&](const std::weak_ptr<A> & obj2) { return obj2.expired(); });
    }
};
...