c++functionoptimizationinline

C++ can compilers inline a function pointer?


Suppose I've got a function functionProxy that takes a generic parameter function and call its operator():

template< typename Function > void functionProxy( Function function ) {
    function();
}

The object passed to it may be:


int main( )
{
    functionProxy( Functor() );
    functionProxy( function );
    functionProxy( [](){ std::cout << "lambda!" << std::endl; } );
    return 0;
}

Will the compiler be able to inline function within functionProxy in all the above cases?


Solution

  • Sure thing.

    It knows the value of function is the same as the value it passes it, knows the definition of the function, so just replaces the definition inline and calls the function directly.

    I can't think of a condition where a compiler won't inline a one-line function call, it's just replacing a function call with a function call, no possible loss.


    Given this code:

    #include <iostream>
    
    template <typename Function>
    void functionProxy(Function function)
    {
        function();
    }
    
    struct Functor
    {
        void operator()() const
        {
            std::cout << "functor!" << std::endl;
        }
    };
    
    void function()
    {
        std::cout << "function!" << std::endl;
    }
    
    //#define MANUALLY_INLINE
    
    #ifdef MANUALLY_INLINE
    void test()
    {
        Functor()();
    
        function();
    
        [](){ std::cout << "lambda!" << std::endl; }();
    }
    #else
    void test()
    {
        functionProxy(Functor());
    
        functionProxy(function);
    
        functionProxy([](){ std::cout << "lambda!" << std::endl; });
    }
    #endif
    
    int main()
    {
        test();
    }
    

    With MANUALLY_INLINE defined, we get this:

    test:
    00401000  mov         eax,dword ptr [__imp_std::endl (402044h)]  
    00401005  mov         ecx,dword ptr [__imp_std::cout (402058h)]  
    0040100B  push        eax  
    0040100C  push        offset string "functor!" (402114h)  
    00401011  push        ecx  
    00401012  call        std::operator<<<std::char_traits<char> > (401110h)  
    00401017  add         esp,8  
    0040101A  mov         ecx,eax  
    0040101C  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401022  mov         edx,dword ptr [__imp_std::endl (402044h)]  
    00401028  mov         eax,dword ptr [__imp_std::cout (402058h)]  
    0040102D  push        edx  
    0040102E  push        offset string "function!" (402120h)  
    00401033  push        eax  
    00401034  call        std::operator<<<std::char_traits<char> > (401110h)  
    00401039  add         esp,8  
    0040103C  mov         ecx,eax  
    0040103E  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401044  mov         ecx,dword ptr [__imp_std::endl (402044h)]  
    0040104A  mov         edx,dword ptr [__imp_std::cout (402058h)]  
    00401050  push        ecx  
    00401051  push        offset string "lambda!" (40212Ch)  
    00401056  push        edx  
    00401057  call        std::operator<<<std::char_traits<char> > (401110h)  
    0040105C  add         esp,8  
    0040105F  mov         ecx,eax  
    00401061  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401067  ret  
    

    And without, this:

    test:
    00401000  mov         eax,dword ptr [__imp_std::endl (402044h)]  
    00401005  mov         ecx,dword ptr [__imp_std::cout (402058h)]  
    0040100B  push        eax  
    0040100C  push        offset string "functor!" (402114h)  
    00401011  push        ecx  
    00401012  call        std::operator<<<std::char_traits<char> > (401110h)  
    00401017  add         esp,8  
    0040101A  mov         ecx,eax  
    0040101C  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401022  mov         edx,dword ptr [__imp_std::endl (402044h)]  
    00401028  mov         eax,dword ptr [__imp_std::cout (402058h)]  
    0040102D  push        edx  
    0040102E  push        offset string "function!" (402120h)  
    00401033  push        eax  
    00401034  call        std::operator<<<std::char_traits<char> > (401110h)  
    00401039  add         esp,8  
    0040103C  mov         ecx,eax  
    0040103E  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401044  mov         ecx,dword ptr [__imp_std::endl (402044h)]  
    0040104A  mov         edx,dword ptr [__imp_std::cout (402058h)]  
    00401050  push        ecx  
    00401051  push        offset string "lambda!" (40212Ch)  
    00401056  push        edx  
    00401057  call        std::operator<<<std::char_traits<char> > (401110h)  
    0040105C  add         esp,8  
    0040105F  mov         ecx,eax  
    00401061  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40204Ch)]  
    00401067  ret
    

    The same. (Compiled with MSVC 2010, vanilla Release.)