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.