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>
.
Honestly, you should just look at https://cdecl.org/, which describes
int (*(*foo())())();
as:And then realize that this is C++11, and we have a really nice syntax for declaring function pointer aliases:
There's really no reason to write declarations like that today.
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[]
(type1, type2)
*
Keep doing this in a spiral/clockwise direction until all tokens have been covered. Always resolve anything in parenthesis first!
Here:
foo
is a function returning a pointer to a function returning a pointer to a function returning atemp<int>
.And now, @UKmonkey just renamed this rule The C++ Guru Snail Rule or CGSR for short:
Correctly formatting the code may help you comprehend:
The
template class
part remains the same so I'm not going to elaborate on it. Let's see the functionfoo
.In the first code, the return value of
foo()
isauto(*)() -> tmp<int>(*)()
, which is a pointer to a function returning another pointer, which points to a function returningtmp<int>
.As you can always define a function pointer like:
Recursing the
pointer_name
with a function (i.e.func_name()
) can declare a function whose return value is such a pointer:So now
(*func_name())(parameter_list)
can serve another function. Let's put it back into the function pointer definition syntax:Clear the parameter list (they're empty) and replace the identifiers with the correct types gives:
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.
cdecl is an useful online tool to demystify complicated C declarations.
Inserting
int (*(*foo())())()
returns:I've replaced
tmp<int>
withint
as the tool does not support templates.