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

Unable to compare std::chrono::duration with zero


In a template class I am working on, I want to check a precondition that a std::chrono::duration is positive, but my compiler complains that it can not instantiate the needed operator< template.

Here is a minimal example (not my original container) of the problem:

 #include <chrono>
 #include <cassert>
 #undef NDEBUG

 template< typename VALUE >
 class Container final
 {
  public:
   using Interval = std::chrono::duration< unsigned int >;

   Container(const Interval interval_):
     interval(interval_),
     value(0)
     {
       assert(Interval::zero < interval_);
     }

  private:
   Interval interval;
   VALUE value;
 };

 template class Container< unsigned int >;

The compiler complains about the assert statement, thus:

 In file included from /usr/include/c++/6/cassert:44:0,
             from main.cpp:2:
 main.cpp: In constructor ‘Container<VALUE>::Container(Container<VALUE>::Interval)’:
 main.cpp:15:29: error: no match for ‘operator<’ (operand types are ‘std::chrono::duration<unsigned int>()’ and ‘const Interval {aka const std::chrono::duration<unsigned int>}’)
        assert(Interval::zero < interval_);
          ~~~~~~~~~~~~~~~^~~
 In file included from main.cpp:1:0:
 /usr/include/c++/6/chrono:668:7: note: candidate: template<class _Clock, class _Dur1, class _Dur2> constexpr bool std::chrono::operator<(const std::chrono::time_point<_Clock, _Duration1>&, const std::chrono::time_point<_Clock, _Duration2>&)
        operator<(const time_point<_Clock, _Dur1>& __lhs,
        ^~~~~~~~
 /usr/include/c++/6/chrono:668:7: note:   template argument deduction/substitution failed:
 In file included from /usr/include/c++/6/cassert:44:0,
                  from main.cpp:2:
 main.cpp:15:31: note:   mismatched types ‘const std::chrono::time_point<_Clock, _Duration1>’ and ‘std::chrono::duration<unsigned int>()’
   assert(Interval::zero < interval_);
                           ^
 In file included from main.cpp:1:0:
 /usr/include/c++/6/chrono:489:7: note: candidate: template<class _Rep1, class _Period1, class _Rep2, class _Period2> constexpr bool std::chrono::operator<(const std::chrono::duration<_Rep1, _Period1>&, const std::chrono::duration<_Rep2, _Period2>&)
   operator<(const duration<_Rep1, _Period1>& __lhs,
   ^~~~~~~~
 /usr/include/c++/6/chrono:489:7: note:   template argument deduction/substitution failed:
 In file included from /usr/include/c++/6/cassert:44:0,
             from main.cpp:2:
 main.cpp:15:31: note:   mismatched types ‘const std::chrono::duration<_Rep1, _Period1>’ and ‘std::chrono::duration<unsigned int>()’
        assert(Interval::zero < interval_);

What have I done wrong?

Or is this a compiler bug? My compiler is g++ (Debian 6.3.0-18+deb9u1) 6.3.0 2017051, on Debian 6.


Solution

  • Try with Interval::zero(). Interval::zero is a function, so you are comparing a duration with a function.

    As a side note, I would suggest to make your Interval argument in the constructor a template, so that you can accept other duragion scales (seconds, ms, us, etc.)

       template < typename Interval2 >
       explicit Container(const Interval2 interval_):
         interval(interval_),
         value(0)
         {
           assert(Interval2::zero() < interval_);
         }
    

    The std::chrono::duration constructor will adapt the tick count transparently, following both Period parameter types.