2
\$\begingroup\$
double time_in_seconds() {
    std::chrono::time_point<std::chrono::system_clock,std::chrono::microseconds> tp = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now());
    auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
    std::time_t time_micro = tmp.count();
    return time_micro / 1000000.0;
}

Here C++11 chrono is used to be able run on multi platform. Use high_resolution_clock to hope to get precision of micro second. std::time_t should be enough to hold this number.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to Code Review! You might get better reviews if you show a little more of the context, such as a sample main that shows how you intend to use this function. \$\endgroup\$ – Edward Sep 24 '18 at 15:28
  • \$\begingroup\$ Very few computing devices can achieve an absolute time accuracy of a few microseconds. Such precision might be useful within a single device, but this is supposed to be cross-platform. How can such precise time values on different devices be useful? \$\endgroup\$ – Gerard Ashton Sep 24 '18 at 23:50
  • \$\begingroup\$ Your code doesn't compile with clang 8, but does with gcc 9. I suspect cross-compiler is necessary to achieve cross-platform ;-) (btw the cause is an impossible conversion from stdeady_clock to system_clock) \$\endgroup\$ – papagaga Sep 25 '18 at 9:09
3
\$\begingroup\$

Leveraging the standard library is the best way to obtain cross-platform code, so you're on the right track. The problem is that your doesn't compile with one of the compilers I've tested it with (clang 8). Using auto would make your code simpler and avoid problematic conversions:

double time_in_seconds() {
    // now compiles with both clang 8 and gcc 9
    auto tp = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now());
    auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
    auto time_micro = tmp.count();
    return time_micro / 1000000.0;
}

Besides, there is no need for those intermediary, ill-named variables tp and tmp. If your function is contained in an implementation file (.cpp), where it should be, importing the std::chrono namespace is perfectly fine, and it becomes quite readable:

double time_in_seconds() {
    using namespace std::chrono;
    return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count() / 1000000.0;
}

auto would also be a better choice for the return type:

auto time_in_seconds() {
    using namespace std::chrono;
    return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count()
           / 1000000.0l; // long double literal
}

auto here avoids any discrepancy between the promotion done in the arithmetic operation (the division by 1.000.000) and the promotion to the return type. For instance:

long double foo() { // seemingly long double precision
    return some_integer / 100.01f; // actually float precision
}

A last improvement I think of is the use of enhanced literals:

auto time_in_seconds() {
    using namespace std::chrono;
    return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count() 
           / 1'000'000.0l; // you can separate thousands with '
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I recommend L for the "long" suffix - .0l looks a lot like .01 at first reading... And consider scientific notation for a power of 10 - perhaps subjective, but I find 1e6L easier than counting zeros. \$\endgroup\$ – Toby Speight Sep 25 '18 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.