Search code examples
c++c++11inlinestdbind

Creating a function alias


EDIT: This question was originally titled "Using std::bind to create inline function," but that's not really what I'm after: I just want a simple way to alias functions.

I would like to expose std::chrono::high_resolution_clock::now as a standalone function. That is, I would like to do the following:

auto current_time = std::bind(std::chrono::high_resolution_clock::now);

Unfortunately, since this is in a header file, it results in multiple definitions of current_time at link-time. Is there a way to return an inline function from std::bind?


Solution

  • Here's what I do if I want to create a simple function alias

    constexpr auto &&now = std::chrono::high_resolution_clock::now;
    

    and if I want to create a full wrapper alias that will be inlined

    template<typename ... Args>
    inline constexpr auto now(Args &&... args) -> decltype(std::chrono::high_resolution_clock::now(std::forward<Args>(args)...)){
        return std::chrono::high_resolution_clock::now(std::forward<Args>(args)...);
    }
    

    The reason why I use a universal reference auto&& in the alias definition is because of the possibility of addressof(now) == addressof(std::chrono::high_resolution_clock::now).

    On my system with G++ 4.9.2 running this:

    constexpr auto &&now_ref = std::chrono::high_resolution_clock::now;
    constexpr auto now_var = std::chrono::high_resolution_clock::now;
    
    template<typename ... Args>
    inline constexpr auto now_wrapper(Args &&... args)
        -> decltype(std::chrono::high_resolution_clock::now(std::forward<Args>(args)...)){
        return std::chrono::high_resolution_clock::now(std::forward<Args>(args)...);
    }
    
    int main(int argc, char *argv[]){
        std::cout << std::hex << std::showbase;
        std::cout << (uintptr_t)std::addressof(std::chrono::high_resolution_clock::now) << '\n';
        std::cout << (uintptr_t)std::addressof(now_wrapper<>) << '\n';
        std::cout << (uintptr_t)std::addressof(now_var) << '\n';
        std::cout << (uintptr_t)std::addressof(now_ref) << '\n';
    }
    

    I get the following results:

    0x4007c0
    0x400a50
    0x400ae8
    0x4007c0
    

    Showing that only the auto&& is actually a direct alias of the function, whereas all other methods have some level of indirection. (although, after compilation they may be replaced by inlined function calls. maybe.)