ned14 / outcome

Provides very lightweight outcome<T> and result<T> (non-Boost edition)
https://ned14.github.io/outcome
Other
676 stars 62 forks source link

Specify type in OUTCOME_TRY? #197

Closed DaanDeMeyer closed 4 years ago

DaanDeMeyer commented 4 years ago

I'm wondering if its's possible to create a version of OUTCOME_TRY that takes the type as an argument instead of using auto.

For example: OUTCOME_TRY(int, a, plus(1, 2)). I tried changing the existing macros but I'm stuck doing the macro overloading on the type argument (first) instead of the expression argument (last).

Any thoughts on whether this is possible?

ned14 commented 4 years ago

It can't be done for OUTCOME_TRY. Or, rather, to make it work for that macro, one would have to sacrifice template parameter use on the right hand side, which I am not willing to do.

A new macro could be implemented, but I would like to see a compelling use use first.

DaanDeMeyer commented 4 years ago

The primary use cases are all the arguments usually used against the use of auto everywhere. It's hard to know the type of a variable declared using OUTCOME_TRY` at a glance since the type isn't explicitly specified.

However, I'm not arguing for including this macro directly in Outcome since I realize it might be controversial. I was just hoping for some pointers on how to implement it so I can use it in my own codebase. The main problem in implementing it seems to be the use of a template parameter in the first argument instead of the last and I'm not sure how to reconcile that with VA_ARGS.

akrzemi1 commented 4 years ago

The implementation difficulties I foresee is that type names may contain commas that the preprocessor will interpret differently:

OUTCOME_TYPED_TRY(std::map<int, int>, m, makeMap<int, int>(1, 1));

we think about it as three parameters passed to preprocessor, but preprocessor sees 5:

5 parameters:
std::map<int
int>
m
makeMap<int
int>(1, 1)

Current macro OUTCOME_TRY can handle the second "strange split" because it happens at the end: it uses variadic macros. But if we need to handle two "strange splits" this becomes next to impossible. Users would have to use an auxiliary macro:

OUTCOME_TYPED_TRY(OUTCOME_WRAP(std::map<int, int>), m, makeMap<int, int>(1, 1));

And I would not be comfortable recommending this.

ned14 commented 4 years ago

Exactly the problem I was referring to @akrzemi1, thanks for explaining it.

If the compelling use case is simply one against auto variables, to be honest what I do in my code where I want the unpacked type to be constrained is:

OUTCOME_TRY(_v, func());
specific_type v = std::move(_v);
...

I only do this where I think it is important to be specific for long term code maintenance, or I encountered surprise. Most of the time the auto type is not awful -- not ideal sure, but not awful either.