Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A strange error in chrono code "C2440: '<function-style-cast>' : cannot convert from '_CR' to 'std::chrono::milliseconds'"

I stumbled upon a strange error

C2440: '' : cannot convert from '_CR' to 'std::chrono::milliseconds'

in what amounts basically to Howard Hinnant's code in another question.

Should this compile on Visual Studio 2012 RC? What would be the reason for this problem? How about a fix or a workaround? My aim is just to create a simple timer (nothing too serious), so if there exists something to that effect, point will be taken -- as well as other implementation cues.

The code in question is as follows. Usage:

  timers::stopwatch w;
  w.start();
  std::cout << to_milliseconds(w.elapsed()) << std::endl;

And the header file is (implementation ommitted for breverity)

namespace timers
{
    class stopwatch
    {
        public:
            typedef std::chrono::high_resolution_clock clock;
            typedef clock::time_point time_point;
            typedef clock::period period;
            typedef std::chrono::duration<float, period> duration;

            stopwatch();
            ~stopwatch();

            void start();
            void stop();
            void restart();
            void reset();

            duration elapsed() const;
       private:
            clock timer_;
            time_point start_point_;
            time_point end_point_;
            bool is_running_;

            void start_measuring();
            void stop_measuring();
     };
}

//Some convenience stuff...
namespace
{       
    long long to_milliseconds(timers::stopwatch::duration const& duration) { return   std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); }
    long long to_nanoseconds(timers::stopwatch::duration const& duration) { return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count(); }
    long long to_seconds(timers::stopwatch::duration const& duration) { return std::chrono::duration_cast<std::chrono::seconds>(duration).count(); }

}

Edit

As as per Howard Hinnant's note, there's #include <chrono> in the header, the implementation file and the calling file. The error points to MS <chrono> header and the error is triggered in this code

// duration_cast
template<class _To,
    class _Rep,
    class _Period> inline
    typename enable_if<_Is_duration<_To>::value,
        _To>::type
        duration_cast(const duration<_Rep, _Period>& _Dur)
        {    // convert duration to another duration
            typedef typename ratio_divide<_Period, typename _To::period>::type _CF;
            typedef typename common_type<
            typename common_type<typename _To::rep, _Rep>::type,
                intmax_t>::type _CR;
                if (_CF::num == 1 && _CF::den == 1)
                    return (_To(static_cast<typename _To::rep>(_Dur.count())));
                else if (_CF::num != 1 && _CF::den == 1)
                    return (_To(static_cast<typename _To::rep>(static_cast<_CR>(_Dur.count())) * static_cast<_CR>(_CF::num)));
                else if (_CF::num == 1 && _CF::den != 1)
            return (_To(static_cast<typename _To::rep>(static_cast<_CR>(_Dur.count()) / static_cast<_CR>(_CF::den))));
                else
                    return (_To(static_cast<typename _To::rep>(xtatic_cast<_CR> _Dur.count()) * static_cast<_CR>(_CF::num) / static_cast<_CR>(_CF::den))));
}

and specifically on line 573 of <chrono>, which on the aforementioned is

 [...]
 else if (_CF::num != 1 && _CF::den == 1)
     return (_To(static_cast<typename _To::rep>(static_cast<_CR>(_Dur.count())) * static_cast<_CR>(_CF::num)));

I can't really follow the purpose of all of that code (yet, at least) to have a definite opinition if it's something in my code somewhere or in the VC++ <chrono> header. I recognise some of naming from TC1/SC22/WG21 n2661. In any event, I'll get back to computer later and see if isolating the stopwatchto a project of its own affects the occurence of this error.

Edit 2

I put the code to an empty project and the problem is still there. As an added note, for the three to_*seconds calls there are six compiler errors. If I put the convenience methods to comments, the code compiles and runs.

Hmm, I wonder what would be a good work-around (or fix)..?

like image 476
Veksi Avatar asked Sep 01 '12 22:09

Veksi


1 Answers

I think that the compile-time error is due to this bug in Visual Studio 2012 RC :

https://connect.microsoft.com/VisualStudio/feedback/details/752794/std-chrono-duration-cast-lacks-double-support

To workaround it, use a duration based on integral type instead of floating point :

#include <cstdint>
//...
typedef std::chrono::duration<std::uint64_t, period> duration;
like image 114
Thomas Petit Avatar answered Sep 26 '22 23:09

Thomas Petit