-
Notifications
You must be signed in to change notification settings - Fork 5
Description
I couldn't find anywhere in the paper (apologies if it's because I didn't look hard enough rather than because it's not there) that talks about the type of a function which uses the new syntax. I note that in the prototype implementation pointers to functions with in, inout and out parameters have different types (https://cppx.godbolt.org/z/96WW7Gdcv) which makes a lot of sense since the requirements each place on the caller is different. It feels like this should be stated explicitly though.
In terms of expressing the types it seems like there may be a bug/limitation in the prototype in that this fails to compile https://cppx.godbolt.org/z/3TanzvYaf
void f(in int a, out int b) { b = 1; }
int main() { void (*y)(in int, out int) = &f; }
because the second parameter doesn't match because it expected out int and got out int. Naturally it's a prototype, not a fully featured implementation of the compiler but what is the intended syntax? Should this compile under the proposal? I note that auto works fine.
This question extends to function like objects as well. How should I express something like std::function<void(in int, out int)>?
I also notice that in int and int are not considered equivalent when comparing function pointer types. This code won't compile due to that incompatibility https://cppx.godbolt.org/z/fefTjd4ah. It's not clear to me whether this is the intention of the proposal.
void f(in int a){}
void unadorned(int a){}
int main() {
auto x = &f;
x = &unadorned;
}
The reason I'm wondering about this is I was considering the confluence of templating as an alternative to virtual functions, requiring write on inout along one code path on non-virtual functions, and requiring (or allowing) inout to be specified at the call site. Consider this code: https://cppx.godbolt.org/z/Ge8fxxe6z (which doesn't compile). In dostuff I want x to be able to modify a so I mark it as inout at the call site. In order for both f and g to be compatible with dostuff I therefore mark their parameters as inout despite the fact that one of them does not need to modify its parameter. As far as I can see this is similar to the virtual function case. We have two functions which can be used interchangeably only one of which has the effect of modifying the inout parameter. As far as I can see, in this case, I either have to
- not specify
inoutat the call site so thatdostuffcan call either type of function - not require
inoutparameters to be written to so thatgremains compatible withdostuff - not implement
dostuffin this way (e.g. by duplicating the code in some sort of overload or with a constexpr if using traits to query whether an inout call is valid).
None of these options seems truly evil but they all have notable drawbacks. Personally if forced to choose I think I would choose the third option but whichever option is chosen it seems like it would need more discussion of the tradeoff in the relevant sections (1.3.6 and 1.3.2 respectively).