Search code examples
c++classtemplatesfunction-pointers

c++ Empty template function returns non-empty function pointer


I am confused by the function pointer of the template function.

See

#include <cstdio>

class A
{
    public:
        A(){}
        ~A(){}
        void command()
        {
            printf("Cmd");   
        }
};

template<class T>
void cmd_create()
{
    T t;
    t.command();
};

int main()
{
    typedef void(*Funcptr)();
    Funcptr f1 = &cmd_create<A>;
    f1();
    return 0;
}

The program output Cmd.

The assembly (-O3) shows that

    .file   "test.cpp"
    .text
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Cmd"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB38:
    .cfi_startproc
    leaq    .LC0(%rip), %rsi
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $1, %edi
    xorl    %eax, %eax
    call    __printf_chk@PLT
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE38:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
    .section    .note.GNU-stack,"",@progbits

Obviously, &cmd_create<A> returns the A::command.

The cmd_create is defined as an empty return (void), however, the code still gets the A::command in such a weird way.

Thank you for your answer!


Solution

  • Obviously, &cmd_create returns the A::command.

    I am not fluent with assembly, but obviously you misunderstand the code ;).

    &cmd_create<A> is a pointer to the function cmd_create<A>. This function pointer is assigned to f1. The pointer is of type void(*)(), pointer to function returning void and no arguments. No function in the code returns anything (if we do not count printf or main).

    f1(); calls the function pointed to by f1. That is: cmd_create<A>. The function creates an object of type A and calls its command member function which prints the output you see on the screen.

    Enabling optimizations means that the compiler emits something that has the same observable behavior. It could emit the same as it would for int main() { printf("Cmd"); }.