Информация об изменениях

Сообщение Re[11]: Какая версия С++ ваша основная? от 13.01.2023 14:24

Изменено 13.01.2023 14:44 rg45

Re[11]: Какая версия С++ ваша основная?
Здравствуйте, Skorodum, Вы писали:

R>>Логически фабрику можно рассматривать как некое расширение конструктора. Соответственно и стратегия обработки ошибок такая же, как в конструкторах — исключения.

S>Наверное, еще std::optional можно использовать.

Не-не-не, это по факту будет равносильно возврату к старой схеме со смарт-поинтерами. Смотрите, какие возможности предоставляет фабрика с mandatory copy/move elision:

http://coliru.stacked-crooked.com/a/4425c094d9731e2d

#include <iostream>
#include <string>
#include <vector>
#include <memory>

struct Foo
{
    const int id;

    explicit Foo(int id) : id(id) {}

    Foo() = default;
    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;
    ////////////////////////////////////////////////////////////////////////////////////////////////
    Foo(Foo&&) = delete;            // перемещение не обязательно запрещать явно
    Foo& operator=(Foo&&) = delete; // оно автоматически запрещается, когда мы запрещаем копирование

    void test() const { std::cout << "Foo: " << id << std::endl; }
};

Foo make_foo()
{
    static int last_id {};
    return Foo(++last_id);
}

int main()
{
    auto foo = make_foo();
    const auto uptr = std::unique_ptr<Foo>(new Foo(make_foo()));
    const auto sptr = std::shared_ptr<Foo>(new Foo(make_foo()));

    foo.test();
    uptr->test();
    sptr->test();
}


То есть, мы можем выбирать стратегию владения объектом за пределами фабрики — вот, что важно. Это может быть любой тип смарпоинтера, а может быть просто объект на стеке с автоматическим временем жизни. Если же изменить тип результата make_foo на std::optional<Foo>, все эти возможности тут же пропадут.
Re[11]: Какая версия С++ ваша основная?
Здравствуйте, Skorodum, Вы писали:

R>>Логически фабрику можно рассматривать как некое расширение конструктора. Соответственно и стратегия обработки ошибок такая же, как в конструкторах — исключения.

S>Наверное, еще std::optional можно использовать.

Не-не-не, это по факту будет равносильно возврату к старой схеме со смарт-поинтерами. Смотрите, какие возможности предоставляет фабрика с mandatory copy/move elision:

http://coliru.stacked-crooked.com/a/8e4325781b2be7cb

#include <iostream>
#include <string>
#include <vector>
#include <memory>

struct Foo
{
    const int id;

    explicit Foo(int id) : id(id) {}

    Foo() = delete;
    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;
    ////////////////////////////////////////////////////////////////////////////////////////////////
    Foo(Foo&&) = delete;            // перемещение не обязательно запрещать явно
    Foo& operator=(Foo&&) = delete; // оно автоматически запрещается, когда мы запрещаем копирование

    void test() const { std::cout << "Foo: " << id << std::endl; }
};

Foo make_foo()
{
    static int last_id {};
    return Foo(++last_id);
}

int main()
{
    auto foo = make_foo();
    const auto uptr = std::unique_ptr<Foo>(new Foo(make_foo()));
    const auto sptr = std::shared_ptr<Foo>(new Foo(make_foo()));

    foo.test();
    uptr->test();
    sptr->test();
}


То есть, мы можем выбирать стратегию владения объектом за пределами фабрики — вот, что важно. Это может быть любой тип смарпоинтера, а может быть просто объект на стеке с автоматическим временем жизни. Если же изменить тип результата make_foo на std::optional<Foo>, все эти возможности тут же пропадут.