In C++23 we have explicit type convertion auto ( expression )
, and according to cppreference it is already supported by both GCC and Clang.
I have a question where such cast does not occur for some reason. Consider the program:
// OK, x = 0
int x(int(auto(0)));
// OK, f is function template
int f(auto(x));
// error
int y(int(auto(x)));
Here x
declaration is accepted, but very similar y
declaration does not. Online demo: https://godbolt.org/z/f9zor3eTv
GCC:
error: 'auto' parameter not permitted in this context
Clang:
error: 'auto' not allowed in function prototype that is not a function declaration
Is declaration of y
really illegal and compilers are correct in rejecting it?
Had you had a type instead of auto
, it would read like:
int y(int(long(x)));
// ->
int y(int(long x));
// ->
int y(int(*)(long));
However, you cannot put auto
in place of long
.
An abbreviated function template is a function declaration that has one or more generic parameter type placeholders ([dcl.spec.auto]). [...]
A placeholder-type-specifier of the form type-constraintopt
auto
can be used as a decl-specifier of the decl-specifier-seq of a parameter-declaration of a function declaration or lambda-expression and, if it is not theauto
type-specifier introducing a trailing-return-type (see below), is a generic parameter type placeholder of the function declaration or lambda-expression.
... So the auto
can only be a decl-specifier
directly in the decl-specifier-seq
of the type, not nested further. Basically, if you can move the auto
all the way to the left, it will work.
So these abbreviated function templates work:
int y(auto x);
int y(auto* x);
int y(auto const*& x);
int y(const auto*& x);
int y(auto* x[][12]);
int y(auto (*x)[3][4]);
int y(auto (*fn)(int x));
// Last one can be written as:
int y(auto(int x));
int y(auto(int(x)));
And these ones won't:
int y(std::vector<auto> x);
int y(void (*fn)(auto));
int y(int x[sizeof(auto)]);
The exact same restrictions apply to placeholder types in initializers, like auto x = ...;
:
int f(int);
auto (*ptr1)(int) = f; // Works
// int (*ptr2)(auto) = f; // Doesn't