Search code examples
c++c++11arithmetic-expressionsc++-chrono

Why does std::chrono::time_point doesn't like arithmetics?


I was simply trying to measure the time passed between to time points:

#include <iostream>
#include <chrono>

int main(){
//    std::chrono::time_point start1;  // <-- doesn't work
//    std::chrono::time_point end1;    // <-- doesn't work
    auto start1;                       // <-- does work
    auto end1;                         // <-- does work

    start1 = std::chrono::high_resolution_clock::now();
    std::cout<<"Hello, World!"<<std::endl;
    end1 = std::chrono::high_resolution_clock::now();

    std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1).count() << std::endl;

    return 0;
}

...and I noticed that start1 and end1 have to be defined with the auto type. If I explicitly define them with the type std::chrono::time_point the expression end1 - start1 gives me "binary operator '-' can not be applied to...".

Why can I use arithmetic operators on start1 and end1 if they are defined with auto? Does auto automatically cast them into something that is compatible with arithmetic operators? I thought auto should just be the shorthand for the compiler to look what std::chrono::high_resolution_clock::now() returns type is?!


Solution

  • I noticed that start1 and end1 have to be defined with the auto type.

    They don't HAVE to be, but it is useful, especially with complex templated types.

    However, you can't declare an auto variable without initializing it in the same statement, otherwise it has nothing to deduce a data type from. It can't deduce a type from another statement, like you attempted to do.

    Try this instead:

    auto start1 = std::chrono::high_resolution_clock::now();
    ...
    auto end1 = std::chrono::high_resolution_clock::now();
    

    If I explicitly define them with the type std::chrono::time_point the expression end1 - start1 gives me "binary operator '-' can not be applied to...".

    std::chrono::time_point is a templated type:

    template< 
      class Clock, 
      class Duration = typename Clock::duration 
    class time_point;
    

    You are not providing any values for its template parameters.

    std::chrono::high_resolution_clock::now() returns a std::chrono::time_point<std::chrono::high_resolution_clock>. If you don't use auto, you have to specify that complete type in your variable declarations:

    std::chrono::time_point<std::chrono::high_resolution_clock> start1 = std::chrono::high_resolution_clock::now();
    ...
    std::chrono::time_point<std::chrono::high_resolution_clock> end1 = std::chrono::high_resolution_clock::now();
    

    Or, if you want to separate the declarations from the assignments:

    std::chrono::time_point<std::chrono::high_resolution_clock> start1;
    std::chrono::time_point<std::chrono::high_resolution_clock> end1;
    
    start1 = std::chrono::high_resolution_clock::now();
    ...
    end1 = std::chrono::high_resolution_clock::now();
    

    You can simplify those a little with using aliases:

    using hi_res_clock = std::chrono::high_resolution_clock;
    using hi_res_time_point = std::chrono::time_point<std::chrono::high_resolution_clock>;
    

    hi_res_time_point start1 = hi_res_clock::now();
    ...
    hi_res_time_point end1 = hi_res_clock::now();
    

    hi_res_time_point start1;
    hi_res_time_point end1;
    
    start1 = hi_res_clock::now();
    ...
    end1 = hi_res_clock::now();
    

    Why can I use arithmetic operators on start1 and end1 if they are defined with auto?

    Because their types will be fully known to the compiler, and it will be able to resolve the appropriate operator- that operates on time_point values.

    Does auto automatically cast them into something that is compatible with arithmetic operators?

    auto is just a shorthand that allows the compiler to auto-deduce a variable's data type based on what is being assigned to that variable at compile-time.

    I thought auto should just be the shorthand for the compiler to look what std::chrono::high_resolution_clock::now() returns type is?!

    That is exactly what it does. You were just not using auto correctly.