From Introduction to the C++11 feature: trailing return types
The article claims
template <class T> class tmp {
public:
int i;
};
auto foo()->auto(*)()->tmp<int>(*)(){
return 0;
}
is equivalent to
template <class T> class tmp{
public:
int i;
};
tmp<int> (*(*foo())())() {
return 0;
}
I don't understand the complex function in the second code example. Where should I look at in the beginning? I guess is foo
. But the stat right next to foo
is going to define foo
as a pointer...
Based on the first code example, I will convert the piece as
tmp<int> (*)() (*)() foo(){ return 0;}
So foo is a function, which returns 0, but the return type is tricky: its return type is functional pointer whose return type is again a function pointer whose return type is tmp<int>
.
In complement with @Vittorio answer, there is the Clockwise Spiral Rule to help us decypher complex types:
Starting with the unknown element, move in a spiral/clockwise direction; when encountering the following elements replace them with the corresponding English statements:
[X]
or []
Array
X
size of... or Array undefined size of...
(type1, type2)
Function passing type1 and type2 returning...
*
pointer(s) to...
Keep doing this in a spiral/clockwise direction until all tokens have been covered. Always resolve anything in parenthesis first!
Here:
+-----------+
| +------+ |
| | >-v | |
temp<int> (*(*foo())())()
| | ^---+ | |
| ^--------+ |
+--------------+
foo
is a function returning a pointer to a function returning a pointer to a function returning a temp<int>
.
And now, @UKmonkey just renamed this rule The C++ Guru Snail Rule or CGSR for short:
/ /
L_L_
/ \
|00 | _______
|_/ | / ___ \
| | / / \ \
| |_____\ \_ / /
\ \____/ /_____
\ _______________/______\.............................
Where should I look at in the beginning?
Honestly, you should just look at https://cdecl.org/, which describes int (*(*foo())())();
as:
declare foo as function returning pointer to function returning pointer to function returning int
And then realize that this is C++11, and we have a really nice syntax for declaring function pointer aliases:
using A = int(*)(); // pointer to function returning int
using B = A(*)(); // pointer to function returning pointer to function returning int
B foo(); // function returning pointer to function returning pointer to function returning int
There's really no reason to write declarations like that today.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With