This question already has an answer here:
-
Complex C declaration
7 answers
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.
cdecl is an useful online tool to demystify complicated C declarations.
Inserting int (*(*foo())())()
returns:
declare foo as function returning pointer to function returning pointer to function returning int
I've replaced tmp<int>
with int
as the tool does not support templates.
Correctly formatting the code may help you comprehend:
template <class T>
class tmp {
public:
int i;
};
auto foo() -> auto(*)() -> tmp<int>(*)() {
return 0;
}
template <class T>
class tmp{
public:
int i;
};
tmp<int> (*
( *foo() )()
)() {
return 0;
}
The template class
part remains the same so I'm not going to elaborate on it. Let's see the function foo
.
In the first code, the return value of foo()
is auto(*)() -> tmp<int>(*)()
, which is a pointer to a function returning another pointer, which points to a function returning tmp<int>
.
As you can always define a function pointer like:
base_type_t (*pointer_name)(parameter_list);
Recursing the pointer_name
with a function (i.e. func_name()
) can declare a function whose return value is such a pointer:
base_type_t (*func_name())(parameter_list);
~~~~~~~~~~~
So now (*func_name())(parameter_list)
can serve another function. Let's put it back into the function pointer definition syntax:
base_type_t (*(*func_name())(parameter_list))(parameter_list);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Clear the parameter list (they're empty) and replace the identifiers with the correct types gives:
base_type_t (*(*func_name())(parameter_list))(parameter_list);
tmp<int> (*(* foo ())( /* Empty */ ))( /* Empty */ );
// Turns to
tmp<int> (*(*foo())())();
As others have already suggested, https://cdecl.org/ is a good code analyzer, though it may give you another sentence which is not quite easy to understand.