Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile error when returning values from a tl::expected with a void expected value #316

Closed
SimonKagstrom opened this issue Oct 6, 2023 · 5 comments

Comments

@SimonKagstrom
Copy link

SimonKagstrom commented Oct 6, 2023

Environment (from conan):

  • trompeloeil v45
  • tl-expected/20190710
  • g++ 11.4.0, -std=gnu++20

I have a problem with mocking tl::expected return values, which has a void expected value (i.e., for a case where only the error value is interesting). I can't figure out how to write the REQUIRE_CALL for the expected value, which in real code would just do a return {}.

Example below. I've tried various other variants, but not found a working solution.

#include <tl/expected.hpp>
#include <trompeloeil.hpp>

class IInterface
{
public:
    virtual ~IInterface() = default;

    virtual tl::expected<const char *, int> Foo() noexcept = 0;
    virtual tl::expected<void, int> Bar() noexcept = 0;
};

class MockInterface : public IInterface
{
public:
    MAKE_MOCK0(Foo, (tl::expected<const char*, int>()), noexcept final);
    MAKE_MOCK0(Bar, (tl::expected<void, int>()), noexcept final);
};

int main()
{
    MockInterface mock;

    // Works
    REQUIRE_CALL(mock, Bar()).RETURN(tl::make_unexpected(1));
    mock.Bar();

    // Works
    REQUIRE_CALL(mock, Foo()).RETURN("hej");
    mock.Foo();

    // How to write this?
    REQUIRE_CALL(mock, Bar()).RETURN({});
    mock.Bar();
}

The error, after a long list of other complaints, boils down to

tl/expected.hpp:2282:26: error: no match for 'operator*' (operand type is 'const tl::expected<void, int>')
 2282 |   return x.has_value() ? *x == v : false;
@rollbear
Copy link
Owner

rollbear commented Oct 6, 2023

Wow, what an interesting find! I'm afraid it may take a while to understand exactly where and how things go wrong here. This is not obvious to me at all.

@SimonKagstrom
Copy link
Author

I've worked around it by changing the interface to return a (slightly contrived) value in the expected case, so no worries!

@rollbear
Copy link
Owner

rollbear commented Oct 9, 2023

Current clang/libc++ main has support for C++23 std::expected, and using that instead works, so I'm leaning towards this being a bug in tl::expected. I'll investigate more, though.

https://godbolt.org/z/qv58jnEov

@rollbear
Copy link
Owner

rollbear commented Oct 9, 2023

It also works with Martin Moene's expected-lite. https://github.com/martinmoene/expected-lite/tree/master

https://godbolt.org/z/oc8eha946

@SimonKagstrom
Copy link
Author

Thanks!

Closing this since it's looks like a bug in tl::expected. We used expected-lite a while back, but for some reason I don't remember, we replaced it with tl::expected. Might be worth reconsidering again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants