Kyle Strand
Kyle Strand

Reputation: 16499

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?

Upvotes: 6

Views: 2395

Answers (5)

RamblingMad
RamblingMad

Reputation: 5518

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.)

Upvotes: 8

tahsmith
tahsmith

Reputation: 1723

Adding another answer 'cause it takes a very different tack to what you want.

std::bind isn't necessary in this case, because no 'binding' is happening.

However I feel this could lead to some confusing problems down the line, since current_time isn't really an alias in the same way that using delcarations are.

#include <iostream>
#include <chrono>

using namespace std;

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

int main() {
    auto now = current_time();
    cout << std::chrono::system_clock::to_time_t(now) << endl;
    return 0;
}

Upvotes: 3

Neil Kirk
Neil Kirk

Reputation: 21773

Keep it simple.

const auto current_time = std::chrono::high_resolution_clock::now;

Upvotes: 2

Jonathan Wakely
Jonathan Wakely

Reputation: 171273

Using GCC it is possible to create a "function alias", but only for functions which are defined in the same translation unit and for which you know the mangled name, so it's not possible to do reliably for std::chrono::high_resolution_clock::now()

See the alias attribute at https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Upvotes: 2

tahsmith
tahsmith

Reputation: 1723

I don't think there is anyway to do this as bind is not constexpr.

Also lambdas are not constexpr-able.

Edit: there is this trick to make a constexpr-like lambda http://pfultz2.com/blog/2014/09/02/static-lambda/

Upvotes: 3

Related Questions