Function Templates

Generic function that can operate with generic types.

template <class T>
T sum(T a, T b) {
    return a+b;
}

int main() {
    cout << sum(4,5);                 // 9
    cout << sum(4.1,5.1);                 // 9.2
    //cout << sum(5,7.8);             // error: no matching function for call to sum(int, double)’
}

//At compile time, compiler creates 2 overloaded versions of sum function.
//sum(int a, int b){ }
//sum(double, double){  }
        

Not Allowed

Double, class object are not allowed template parameters


//ERROR:  ‘double’ is not a valid type for a template non-type parameter
template <double T, typename T1>
void fun () {  }
// if you replace double with int, it will compile

//‘class A’ is not a valid type for a template non-type parameter
class A{};
template <A s, typename T1>
void fun () {   }

//‘class std::__cxx11::basic_string’ is not a valid type for a template non-type parameter
template <string s, typename T1>
void fun () {  }
        

Assembly (Function Templates)


            /*      function_template_assembly.cpp

            ********POINTS TO REMEMBER:**********
            1. Stack grows in reverse direction.
              |----stack grows-----|-------------<<------heap grows------
             0x450                0x200
             rbp                  rsp
            
            2. Arguments to function are stored in registers:  rdi, rsi, rdx, rcx, r8...
            *************************************
            
            **************HOW TEMPLATES WORKS INTERNALLY? *********
            Function overloading
            
             - Types are defined using Angular brackets <>
             - User-defined-function        Complier-generated-function
                    maximum(4,5)            int maximum <int>(int, int)
                    maximum('a','b')        char maximum <char>(char, char)
                    maximum(4,4.5)          int maximum <int, double>(int, double)
            ********************************************************
            
            */
            #include
            using namespace std;
            
            template <class T>                      //OR template 
            T maximum(T a, T b){
                    return (a>b)?a:b;
            }
            
            int main(){
                    cout<<maximum(4,5);
                    cout<<maximum('a','b');
            }
            
            /*
             ASSEMBLY:
            
            int maximum<int>(int, int):
                    push    rbp                     //4a
                    mov     rbp, rsp                //4b
                    mov     DWORD PTR [rbp-4], edi  //5 Arguments of function stored on stack. *(rbp-4)=edi=4
                    mov     DWORD PTR [rbp-8], esi  //5 Arguments of function stored on stack. *(rbp-4)=esi=5
                    mov     eax, DWORD PTR [rbp-4]  //6 eax=*(rbp-4)=4
                    cmp     eax, DWORD PTR [rbp-8]  //7 if(eax == *(rbp-8))
                    jle     .L4
                    mov     eax, DWORD PTR [rbp-4]
                    jmp     .L6
            .L4:
                    mov     eax, DWORD PTR [rbp-8]
            .L6:
                    pop     rbp
                    ret
            
             main:
                    push    rbp             //1a
                    mov     rbp, rsp        //1b
                    mov     esi, 5          //2a.   2nd Function Argument
                    mov     edi, 4          //2b.   1st Function Argument
                    call    int maximum <int>(int, int)      //3
                    mov     esi, eax
                    mov     edi, OFFSET FLAT:_ZSt4cout
                    call    std::basic_ostream<char, std::char_traits >::operator<<(int)
                    mov     esi, 98
                    mov     edi, 97
                    call    char maximum <char>(char, char)
                    movsx   eax, al
                    mov     esi, eax
                    mov     edi, OFFSET FLAT:_ZSt4cout
                    call    std::basic_ostream <char, std::char_traits >& std::operator<<  >(std::basic_ostream >&, char)
                    mov     eax, 0
                    pop     rbp
                    ret
            
            STEPS:
            1. Function Epilogue.
               a.Push value of rbp0 somewhere on stack
               ------------                        Head
               rbp0     rsp0                Stack | rbp0=0x450 |
            
               b.Move rbp to rsp
               --------------main---
                        rbp1     rsp1
            
            2. Store function arguments in registers.       Registers
                                                            edi=4
                                                            esi=5
            3. call maximum function.
            
            4. Function Epilogue.
               a.Push value of rbp1 somewhere on stack
               --------------------                 Head
                       rbp1      rsp1         Stack | rbp0=0x450 | rbp1=0x400 |
            
               b.Move rbp to rsp
               -------main------------maximum(int, int)---
                                 rbp2                        rsp2
            
            5. Store parameters of function onto stack
               -------main------------maximum(int, int)---
                                 rbp2 4 5                    rsp2
            
            6. Store arguments in eax                       Registers
                                                            eax=4
            
            7. Compare operands. Subtracts 1st operand from other for comparing them, updates Flag register to show results.
            */