Search code examples
c++function-pointersarray-pointer

How to read a complicated type?


I know that using type alias and typedef make the code so readable, less error-prone and easy modify. However in this example I want to know this complicated type:

#include <iostream>
#include <typeinfo>

char ( * (* x() )[] )();

int main(){

    std::cout << typeid(x).name() << std::endl;
}

As the rule of thumb says that I read it from inside through outside but I find it too confusing.

Can someone help me how to read it?

The output of GCC:

FPA_PFcvEvE

Solution

  • char        - returning a char                         *
      (*        - of pointers to                    *---v  ^
        (*      - returning a pointer to    *---v   ^   v  ^
           x()  - a function `x`          --^   v   ^   v  ^
        )[]     - an array                      *---^   v  ^
      )();      - functions                             *--^
    

    And see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.array-type , like:

    FPA_PFcvEvE
    ^           - function (
     ^          - returning pointer
      ^         - to an array [
      ><        - with no dimension expression
       ^        - separator, end of array ]
        ^       - of pointers
         ^      - to functions (
          ^     - returning char
           ^    - (void) functions that take no arguments
            ^   - separator, end of function )
             ^  - (void) it's a function that takes on arguments
              ^ - separator, end of function )
    

    Example:

    #include <iostream>
    
    char return_a() { return 'a'; }
    char return_b() { return 'b'; }
    char return_c() { return 'c'; }
    
    char (* array_of_funcs_that_return_char[3])() = {
        return_a,
        return_b,
        return_c,
    };
    
    char (* (*pointer_to_array_of_funcs_that_return_char)[3])() = &array_of_funcs_that_return_char;
    
    char ( * (* x() )[3] )() {
        return pointer_to_array_of_funcs_that_return_char;
    }
    
    int main() {
        std::cout << (*x())[1](); // outputs 'b'
    }