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

Use mutable lambda in SIDE_EFFECT? #252

Open
reddwarf69 opened this issue Sep 3, 2021 · 4 comments
Open

Use mutable lambda in SIDE_EFFECT? #252

reddwarf69 opened this issue Sep 3, 2021 · 4 comments

Comments

@reddwarf69
Copy link
Contributor

reddwarf69 commented Sep 3, 2021

I have a case were I wanted to check something sends some data, and something else receives the same data.
The sender can only send by rvalue reference (I could add a const reference overload, but...).

The thing is that I though about doing something like

    auto result = data{};
    REQUIRE_CALL_V(mock, async_do(trompeloeil::_), .SIDE_EFFECT(_1(std::move(result))));
    REQUIRE_CALL_V(mock, receive(result));

but it doesn't build.
My understanding is that in SIDE_EFFECT it doesn't build because I am trying to move "result", which is a member of the lambda, which is const.

There are other ways to do the same, is not a big deal here. Not even sure this is the best way (I was trying to make clear they both refer to the same "result"... even if it's a lie, it's too different objects). But probably SIDE_EFFECT could use a mutable lambda? Maybe it would solve other scenarios? I can't see any drawback in making it unconditionally mutable, but I guess there could be a MUT_SIDE_EFFECT otherwise.

@rollbear
Copy link
Owner

rollbear commented Sep 3, 2021

.SIDE_EFFECT(...) captures by copy, so even if it worked, it wouldn't do what you intended, because you'd move the copy.

I've thought, for years if you can believe it, about figuring out how to write a SIDE_EFFECT(...) (and others) where you write the capture you want, but it doesn't lend itself very well to how the preprocessor works.

@reddwarf69
Copy link
Contributor Author

In this specific case capturing by copy is exactly what I want. I need to move it, because the async_do interface only lets me do that but still want to have it available later, so moving a copy helps me. I was trying to make it look as if it's the same variable even if I'm lying (which may be a bad idea)... at the end I know I am comparing to value of two copies, which is fine with me.

Uhm... but maybe I am wrong about the "later" part.
In .SIDE_EFFECT(_1(std::move(result)))) result is clearly not going to be moved until async_do, is called.
But in REQUIRE_CALL_V(mock, receive(result));... is result copied into some trompeloeil expectation immediately? Or it's evaluated only when receive() is called?

@reddwarf69
Copy link
Contributor Author

So basically, is

    auto result = data{};
    REQUIRE_CALL_V(mock, async_do(trompeloeil::_), .LR_SIDE_EFFECT(_1(std::move(result))));
    REQUIRE_CALL_V(mock, receive(result));

broken because receive(result) refers to a moved-from result or not?

@rollbear
Copy link
Owner

rollbear commented Sep 3, 2021

Right. And I see what you mean.

You can work around it, but I admit that it's a bit cumbersome:

auto source = data{};
const auto expected = data{}; // holds the same values, compares equal
REQUIRE_CALL_V(mock, async_do(trompeloeil::_), .LR_SIDE_EFFECT(_1(std::move(source))));
REQUIRE_CALL_V(mock, receive(expected));

I'll have to think about this. Something like it may happen down the line, but I don't think it will happen soon. Sorry about that.

Let's keep this open as a reminder.

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

No branches or pull requests

2 participants