Sadly VS2012's duration_cast
is broken, and I actually need the functionality which is broken. So, I wrote my own:
template<typename ToUnit, typename Rep, typename Period>
ToUnit duration_cast_2(const std::chrono::duration<Rep, Period>& right)
{
typedef std::ratio_divide<Period, typename ToUnit::period>::type ratio;
typedef std::common_type<std::common_type<typename ToUnit::rep, Rep>::type, intmax_t>::type common_type;
return ToUnit(static_cast<typename ToUnit::rep>(static_cast<common_type>(right.count()) * static_cast<common_type>(ratio::num) / static_cast<common_type>(ratio::den)));
}
But I'm not entirely confident that it's correct.
1 Answer 1
I can't say for sure about the internal logic but I can point some problems or things that could be improved in your piece of code:
First of all,
typename
is missing before the names, making your code non-working with some compilers. I would also useusing
instead oftypedef
, but that's a mere matter of taste. Updated version:using ratio = typename std::ratio_divide<Period, typename ToUnit::period>::type; using common_type = std::common_type<typename std::common_type<typename ToUnit::rep, Rep>::type, intmax_t>::type;
std::common_type
is variadic. You don't have to bother with nestedstd::common_type
s:using common_type = typename std::common_type<typename ToUnit::rep, Rep, intmax_t>::type;
I know that MSVC has not a full support for
constexpr
, butduration_cast
is supposed to beconstexpr
(it should work with the November 2013 CTP though):template<typename ToUnit, typename Rep, typename Period> constexpr ToUnit duration_cast_2(const std::chrono::duration<Rep, Period>& right) { // ... }
-
\$\begingroup\$ This was actually more than a year ago, and at the time I was using VS2010, so limited to not doing anything you mentioned above. I was most interested in the correctness of the internal logic. The whole thing was actually because there was a bug in the VS2010 duration_cast implementation. I don't know if it's fixed yet, probably is. \$\endgroup\$David– David2014年03月27日 12:09:25 +00:00Commented Mar 27, 2014 at 12:09
-
\$\begingroup\$ @Dave From the link in your question, the problem seems to have been solved :) \$\endgroup\$Morwenn– Morwenn2014年03月27日 12:18:31 +00:00Commented Mar 27, 2014 at 12:18
-
\$\begingroup\$ Oh, lol. Thanks. Also I guess I was using 2012 not 2010. I didn't reread my question, it was a long time ago =P \$\endgroup\$David– David2014年03月27日 12:25:54 +00:00Commented Mar 27, 2014 at 12:25
std::chrono::duration<long long, std::micro>
into astd::chrono::duration<double, std::milli>
, for example. That conversion cannot be done implicitly, and needs the cast. \$\endgroup\$