Search code examples
c++mingw-w64timingc++-chrono

mismatched types 'std::chrono::_V2::steady_clock' and 'std::chrono::_V2::system_clock'


I'm trying to build my program in mingw64 (GCC v11.2). I have the following struct:

In a header file:

struct Timer
{
    std::chrono::time_point< std::chrono::steady_clock > start;
    std::chrono::time_point< std::chrono::steady_clock > end;

    Timer( );
    ~Timer( );
};

In a source file:

util::Timer::Timer( )
: start( std::chrono::high_resolution_clock::now( ) )
{
}

util::Timer::~Timer( )
{
    end = std::chrono::high_resolution_clock::now( );
    std::chrono::duration< double, std::milli > duration_ms { end - start };
    std::clog << "\nTimer took " << duration_ms.count( ) << " ms\n";
}

But this happens:

error: no matching function for call to 'std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long long int, std::ratio<1, 1000000000> > >::time_point(std::chrono::_V2::system_clock::time_point)'
    8 | : start( std::chrono::high_resolution_clock::now( ) )
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from pch.h:23:
c:\mingw64\include\c++\11.2.0\chrono:871:21: note: candidate: 'template<class _Dur2, class> constexpr std::chrono::time_point<_Clock, _Dur>::time_point(const std::chrono::time_point<_Clock, _Dur2>&) [with _Dur2 = _Dur2; <template-parameter-2-2> = <template-parameter-1-2>; _Clock = std::chrono::_V2::steady_clock; _Dur = std::chrono::duration<long long int, std::ratio<1, 1000000000> >]'
  871 |           constexpr time_point(const time_point<clock, _Dur2>& __t)
      |                     ^~~~~~~~~~
c:\mingw64\include\c++\11.2.0\chrono:871:21: note:   template argument deduction/substitution failed:
Util.cpp:8:3: note:   mismatched types 'std::chrono::_V2::steady_clock' and 'std::chrono::_V2::system_clock'
    8 | : start( std::chrono::high_resolution_clock::now( ) )
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Why is this happening? How to fix it?


Solution

  • Thanks to the information provided in the comments, I came up with the following solution:

    In the header file:

    struct Timer
    {
        std::chrono::time_point< std::chrono::steady_clock > start;
        std::chrono::time_point< std::chrono::steady_clock > end;
    
        Timer( );
        ~Timer( );
    };
    

    In the source file:

    util::Timer::Timer( )
    : start( std::chrono::steady_clock::now( ) )
    {
    }
    
    util::Timer::~Timer( )
    {
        end = std::chrono::steady_clock::now( );
        std::clog << "\nTimer took " << std::chrono::duration< double, std::milli >( end - start ).count( ) << " ms\n";
    }
    

    So in short, I switched from std::chrono::high_resolution_clock::now( ) to std::chrono::steady_clock::now( ) because high_resolution_clock has different implementations on different compilers according to high_resolution_clock.
    On some of them it returns std::chrono::time_point<std::chrono::steady_clock> and in some others it returns std::chrono::time_point<std::chrono::system_clock>. And that caused problems for me.

    A note from cppreference:

    Notes

    The high_resolution_clock is not implemented consistently across different standard library implementations, and its use should be avoided. It is often just an alias for std::chrono::steady_clock or std::chrono::system_clock, but which one it is depends on the library or configuration. When it is a system_clock, it is not monotonic (e.g., the time can go backwards). For example, for gcc's libstdc++ it is system_clock, for MSVC it is steady_clock, and for clang's libc++ it depends on configuration.

    Generally one should just use std::chrono::steady_clock or std::chrono::system_clock directly instead of std::chrono::high_resolution_clock: use steady_clock for duration measurements, and system_clock for wall-clock time.