Копирование / перемещение объекта в g cc нарушает его член лямбды - PullRequest
1 голос
/ 30 апреля 2020

Допустим, существует простое полиморфное c отношение:

class base {
public:
    void update() const { updater(); }
    void accept(visitor const &visitor) {
        visitor_acceptor(visitor);
    }
protected:
    base(std::function<void()> const &updater, 
         std::function<void(visitor const &)> const &visitor_acceptor) 
        : updater(updater), visitor_acceptor(visitor_acceptor) {}
protected:
    std::function<void()> updater;
    std::function<void(visitor const &)> visitor_acceptor;
};

class derived_int : public base {
public:
    derived_int() : base(
            [this]() { ++value; }, 
            [this](visitor const &visitor) { visitor(value); }
        ), value(0) {}
protected:
    int value;
};

class derived_string : public base {
public:
    derived_string() : base(
            [this]() { value += '1'; }, 
            [this](visitor const &visitor) { visitor(value); }
        ), value("") {}
protected:
    std::string value;
};

и класс хранения для хранения их всех вместе:


class storage {
public:
    void add(base const &input) { pointers.emplace_back(std::make_unique<base>(input)); }
    void add(base &&input) { pointers.emplace_back(std::make_unique<base>(std::move(input))); }

    void update() {
        for (auto &ptr : pointers)
            ptr->update();
    }
    void print() {
        visitor printer;
        for (auto &ptr : pointers)
            ptr->accept(printer);
    }
private:
    std::vector<std::unique_ptr<base>> pointers;
};

main:

int main() {
    storage s;

    derived_int temp1;
    derived_string temp2;
    s.add(temp1);
    s.add(temp2);
    s.add(derived_int{});
    s.add(derived_string{});

    for (size_t i = 0; i < 5; i++)
        s.update();

    s.print();
}

На clang (10.0) и MSVC (19.25) этот mcve работает правильно, а gcc (9.3.0) выводит:

derived_int: 5
derived_string: 11111
derived_int: -71963
derived_string: 1

Кажется, что существует какая-то проблема жизни объекта , поскольку явно созданные переменные не вызывают никаких проблем, но я не могу точно определить их.

...