Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow std::expected to use a private constructor

Tags:

c++

c++23

I try to create a non-copyable and non-movable class, whose object construction should only be done via a create function instead of public constructors. The create function will return a std::expected object either holding the created object or an error object. In order to enforce construction via the create function I want to make all available constructors private. Main purpose of this approach is object construction without exceptions.

Here is a simple example:

class Foo
{
    int val_{};

public:
    Foo() = delete;
    Foo(const Foo&) = delete;
    Foo& operator=(const Foo&) = delete;

    static auto
    create(int val) noexcept -> std::expected<Foo, std::error_code>
    {
        if (val == 42)
            return std::unexpected<std::error_code>(std::in_place, EINVAL, std::generic_category() );

        return std::expected<Foo, std::error_code>{ std::in_place, val };
    }

private:

    friend class std::expected<Foo, std::error_code>;

    explicit Foo(int val) noexcept
    : val_{ val }
    {};

};

Please note, that I made std::expected<Foo, std::error_code> a friend in order to allow it to call the private constructor. But still I get a compiler error. Here is the code in Compiler Explorer.

like image 823
k.st. Avatar asked Apr 28 '26 00:04

k.st.


1 Answers

You can use expected::transform:

static auto
create(int val) noexcept -> std::expected<Foo, std::error_code>
{
    if (val == 42)
        return std::unexpected<std::error_code>(std::in_place, EINVAL, std::generic_category() );
    
    return std::expected<int, std::error_code>{val}.transform(
      [](int i) { return Foo{i}; }
    );
}

Demo

like image 188
康桓瑋 Avatar answered Apr 29 '26 15:04

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!