There is no way to declare such functions. (Unless it can be done with
modules - I am not familiar enough with them yet.) So you'd need to
declare the return type, with a name, then use that to declare the
function - just as you would with C.
C++ makes it easier to have such declarations in header files, however,
and ensures that if the function is generated separately rather than
being expanded inline, you only have one copy in the final linked program.
(Yes, having the definitions of functions in headers makes compilation
slower, and yes, speed of compilation of C++ files /is/ a big issue,
unlike for C. On the other hand, you can often distribute C libraries
as just header files rather than header + implementation pairs. And
modules will improve build times significantly.)
>
> What I'm getting at is that such a return type will need to be known at
> the call-site, at least the number and types of the multiple values.
>
Yes, exactly.
> Also I can't see that 'auto' helps that much here, since you will still
> need to know the number of return values, if not their types.
Functions with "auto" return type (and no trailing return type) have
their real return types inferred by the compiler when it sees their
definition. So you can't declare them in advance. But for a lot of
functions, there is only one "return" statement and you let the compiler
do the work for you.
Use of inferred types is, if you like, a higher level feature. It is
not always the right choice, and it is not always possible. You use
inferred types when you are most interested in features of the type,
rather than details of the implementation, or when you only want to
assign it once.
For example, if you write "auto x = foo();", then you know "x" is of a
type that can hold any value that foo() might return. But if you then
go on to write "x += 1;", you might not know if that is valid - perhaps
the type of "x" is "int" and this overflows, and you really wanted to
write "unsigned int x = foo();".
"auto" really comes in handy when dealing with generic functions
(templated functions or concept functions), or when you have complicated
types that you don't want to have to write out manually.
"auto" makes it easier to write some kinds of code error-free, and also
makes it easier to make other kinds of errors. It is a helpful feature
but not a magic feature.
>
> (Your proposal also seems to allow multiple, nested return values, which
> IMO is not useful and complicates matters. That would be better as a
> single compound type.)
My example above (foo and bar) is giving a single compound return. You
can do that in C too, but you have to be more verbose and explicit.
That can be a good thing and a bad thing - there are no absolutes here.
(I can't stress that enough.)
>
> This is a
>> good thing, and a good use of "auto" (IMHO, of course). "bar2" uses
>> structured bindings, and shows the kind of subtle mistake that is
>> easily made here. (Unlike some of the mistakes you discussed about
>> structured bindings, this mistake compiles fine so you get no help
>> from the tools.)
>
> C, and I assume C++, allows this:
>
> void fn(int sum, int prod);
> void fn(int prod, int sum) {....}
>
> If only the declaration is visible at the call-site, it will be misleading.
Yes. That is one thing I strongly dislike about the languages, and it
is a big hinder to having a simple system of named parameters. However,
it is also clear that there are some /good/ reasons for allowing
different names for parameters.
>
>> However, AFAIK C++ currently gives no way to use such anonymous struct
>> return types in functions with separate definitions and declarations.
>
> OK, you seem to have answered my point above...
With luck, someone will answer it differently, and I'll learn something
useful!
>
> >
> > So you think two wrongs makes a right? There are a few people who post
> > regularly in c.l.c. about how bad or pointless C is, and why C++ or
> > their own made-up language is vastly better.
>
> It might worth listening to such people when their made-up (but actual,
> not imaginary) language has long had features such as multiple return
> types, default parameter values and keyword arguments. And that sum/prod
> mixup is not possible.
Sometimes comparisons between languages are useful, yes. Endless "/my/
language is so much better" posts are not. There is a difference.
>
> Example after sig.
>
Put things before the signature if they are useful (even if they are not
in the language of the group) - otherwise they get snipped.