23

You can use a typedef to create a shorter and simpler name for types:

typedef std::chrono::high_resolution_clock Clock;
typedef Clock::time_point TimePoint;
typedef std::chrono::seconds Seconds;
typedef std::chrono::milliseconds Milliseconds;

As well as for instantiated templated types:

typedef std::chrono::duration<float, std::ratio<1>> RealDuration;

// Example usage
float dt = RealDuration(a - b).count();

And for function pointers:

typedef void (*FuncPtr)(int,int);

You can also use type aliases for templates:

template<typename T> using uptr = std::unique_ptr<T>;

// Example usage
uptr<int> myInt;
uptr<foo> myFoo;

But how can you create an alias/pointer to a templated function? For example, if I want to be able to use the name DurationCast to write things like this:

x = DurationCast<Seconds>(a - b);
y = DurationCast<Milliseconds>(c - d);

What needs to be done to shorten the function std::chrono::duration_cast<T>() to just DurationCast<T>() without simply going the using namespace std::chrono; or using std::chrono::duration_cast; route, and without writing my own function objects to achieve it?

EDIT: I guess I can just write a simple wrapper around it:

template<typename ToType, typename FromType>
ToType DurationCast(const FromType& d)
{
    return std::chrono::duration_cast<ToType>(d);
}

Doesn't work like an alias, but the end result is that I can use it in the exact same way I was aiming for:

x = DurationCast<Seconds>(a - b);
derpface
  • 1,611
  • 1
  • 10
  • 20
  • Fyi, [`duration_cast`](http://en.cppreference.com/w/cpp/chrono/duration/duration_cast) is in `std::chrono`; not just `std`. I imagine `using std::chrono;` to avoid slurping in all of `std` is likewise off your radar, even though that is what nearly *everyone* ends up doing. – WhozCraig Oct 03 '14 at 18:02
  • Whoops, I knew that. Fixed question. – derpface Oct 03 '14 at 18:04
  • @derpface: you can template a variable which is a pointer to function, but then you have to specify all arguments, e.g. `DurationCast>(s)`, does this suit you? – Piotr Skotnicki Oct 03 '14 at 18:05
  • @derpface: or at least know prior to declaration, what is representation and period – Piotr Skotnicki Oct 03 '14 at 18:07
  • Relatively sure you'll have to wrap the function instead of using a `typedef` - you can `typedef` function pointers, but not functions AFAIK (please correct and @reference me in a comment if I'm wrong!) – Conduit Oct 03 '14 at 18:13
  • @derpface also, the utility of that namespace is important, because nearly *all* of `std::chrono` is wrought with functions that require other functions, types, enums, etc, *from `std::chrono`*. Ie. the `chrono` functions would be near worthless `using` stand-alone artifacts. `DurationCast` may have saved you typing 13 additional characters, but `blah` still needs to be spelled out as in your typedef, `std::chrono::milliseconds` for example. At least `using namespace std::chrono` gives you a way to pull in `chrono` without polluting the rest of the tu like `using namespace std;` would. – WhozCraig Oct 03 '14 at 18:14
  • @WhozCraig That's true, but the chrono stuff was more or less just for demonstration purposes. The question was intended to be more general. – derpface Jan 08 '15 at 14:51
  • See also https://stackoverflow.com/a/9864472/490560 – Ignitor Aug 14 '19 at 14:04

2 Answers2

18

how can you create an alias/pointer to a templated function?

You can alias a variable of a function pointer type:

template <typename T>
void foo()
{
    std::cout << "foo!" << (T)3.14f << std::endl;
}

template <typename T>
constexpr void(*foo_alias)() = &foo<T>;

int main()
{
   foo_alias<int>();    // 3
   foo_alias<float>();  // 3.14
}

For example, if I want to be able to use the name DurationCast (...) What needs to be done to shorten the function std::chrono::duration_cast<T>() to just DurationCast<T>() ?

The trick with a pointer to function is that you have to specify all types of arguments to get the address of a function, as such, you need all parameters' types explicitly given or templated. Unfortunately, std::chrono::duration_cast takes three parameters:

template <typename T, class Rep, class Period>
constexpr T(*DurationCast)(const std::chrono::duration<Rep, Period>&) = &std::chrono::duration_cast<T, Rep, Period>;

std::chrono::seconds s(1);
std::chrono::milliseconds ms = DurationCast<std::chrono::milliseconds, float, std::ratio<1>>(s);
//                                                                     ~~~~^  ~~~~~~~~~~~~^
//                                                       explicit representation and period

DEMO

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • This answers the question brilliantly! (unlike the accepted answer) In particular, I needed this in order to change which template arguments are necessary (to 0, in fact). Can you comment on whether you would actually use this in favour of the more easy to understand function call, which would probably get inlined anyway? – TamaMcGlinn Oct 28 '20 at 20:23
  • 1
    Good answer. This becomes even nicer with `auto` (for example `template auto foo_alias = &foo;`). – Smiley1000 Sep 19 '21 at 11:05
11

You can create a helper function which forwards to duration_cast:

template <typename T, typename U>
auto DurationCast(U const& u) -> decltype(std::chrono::duration_cast<T>(u))
{
    return std::chrono::duration_cast<T>(u);
}
user2030677
  • 3,448
  • 4
  • 23
  • 36
  • "and without writing my own function objects to achieve it?" But I agree, this is pretty much as close at it gets, other than `#define` – Creris Oct 03 '14 at 18:12
  • Doh, I didn't refresh the page before editing my post, but this is basically the conclusion I came to, except without the auto/decltype. – derpface Oct 03 '14 at 20:41