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.