2

I know, that to shorten class names I can do the following:

using Time = std::chrono::time_point<std::chrono::system_clock>;
using Clock = std::chrono::system_clock;

But how to properly reduce length of the next line?

/*using Ms = */ std::chrono::duration_cast<std::chrono::milliseconds>

The target piece of code:

Time start = Clock::now();
// something
Time end = Clock::now();
std::cout << Ms(end - start).count() << std::endl;

4 Answers4

7

You have a couple options. You could use a using declaration:

void foo() {
    // These can be scoped to the function so they don't bleed into your API
    using std::chrono::duration_cast;
    using std::chrono::milliseconds;

    Time start = Clock::now();
    // something
    Time end = Clock::now();
    std::cout << duration_cast<milliseconds>(end - start).count() << std::endl;
}

Alternatively, you could write your own function:

template <typename Duration>
auto as_ms(Duration const& duration) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(duration);
}

void foo() {
    Time start = Clock::now();
    // something
    Time end = Clock::now();
    std::cout << as_ms(end - start).count() << std::endl;
}
Justin
  • 24,288
  • 12
  • 92
  • 142
  • See, now your answer is an answer! My comment was just a notion. ;-) – Eljay Mar 13 '18 at 18:15
  • @Eljay Yes, but there's no reason why you couldn't have posted that as an answer. :) – Justin Mar 13 '18 at 18:16
  • So, why not inline auto as Eljay stated? –  Mar 13 '18 at 18:19
  • You could also have a single `using`-declaration for the entire `std::chrono` namespace. I understand why you might not want a `using`-declaration for a whole namespace in a larger scope, but for a function of this size the danger seems minimal. – Ben S. Mar 13 '18 at 18:19
  • @BenS. I wouldn't recommend `using namespace std::chrono;` It's analogy in other languages is a `*` import (e.g. `import java.util.*;`) It's not a good idea in most cases, as you could easily end up with a name collision. If the number of `using` declarations you need is small (in this case it's only 2), it's not much more typing anyway. OTOH, I do use namespace aliases all the time (`namespace chr = std::chrono;`) – Justin Mar 13 '18 at 18:22
  • @BhavinChirag This is equivalent. You can add the `inline` keyword. Since the function I wrote is a template function, it's implicitly `inline` (it makes no difference to add it). If you want to make the function not a template, you'd have to add the `inline` keyword (assuming you put the definition in a header file). Eljay's function wasn't a template; it used a concrete type as an argument. I tend to prefer templates for situations like this, where there are multiple types that work – Justin Mar 13 '18 at 18:24
  • @Justin Maybe I am wrong but I thought that in some cases compiler will not inline it. –  Mar 13 '18 at 18:27
  • @BhavinChirag The `inline` keyword has an unfortunate name. It isn't a hint to the compiler to inline the function. All it means is that you can put the function definition in a header file. See [this answer](https://stackoverflow.com/a/157929/1896169). However, the compiler will see that all this function does is call another function, so - in practice - this function *will* be inlined by the compiler – Justin Mar 13 '18 at 18:28
3

As of c++17, lambdas are constexpr by default, which makes them excellent aliases for template functions without all the unpleasant template syntax:

#include <chrono>
#include <iostream>

void test()
{
    using Clock = std::chrono::system_clock;
    using Time = Clock::time_point;

    auto Ms = [](auto&& duration)
    {
        return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
    };

    auto start = Clock::now();
    // something
    auto end = Clock::now();
    std::cout << Ms(end - start) << std::endl;
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
2

What you refer to as shortening class names is actually type aliasing. Type aliases are used for types. std::chrono::duration_cast<std::chrono::milliseconds> is not a type. It is a function. You can not make aliases for functions.

Ron
  • 14,674
  • 4
  • 34
  • 47
  • Thank you, it is clear for me. I want to know is there a beautiful solution, because I always can use #define with that string to solve the problem. –  Mar 13 '18 at 18:12
  • There are aliases for function pointers and you can also wrap the function into another function. Whether you should is another subject. – Ron Mar 13 '18 at 18:17
  • 2
    @BhavinChirag I strongly recommend not using a `#define`. If you do want to use it, be certain that you `#undef` it. – Justin Mar 13 '18 at 18:18
  • @Justin Indeed. Definitely avoid `#define` and (too much) macro programming. – Ron Mar 13 '18 at 18:26
-1

The preprocessor is there for you to take advantage of, if you want to, you can just use macros.

#define TIME std::chrono::time_point<std::chrono::system_clock>
#define CLOCK std::chrono::system_clock;
#define TIME_AS_MS std::chrono::duration_cast<std::chrono::milliseconds>
wayfarer
  • 11
  • 6