如何使用`duration_cast`来派生类?

时间:2015-05-31 07:55:41

标签: c++ c++11 chrono

我正在使用std::chrono清理我的计时器类。除了我似乎无法将duration_cast应用于派生类之外,其他所有内容都很顺利。好吧,我让它以不同的方式工作,但我仍然想知道我错过了什么。

请参阅here以获取错误消息。

#include <iostream>
#include <chrono>

typedef std::chrono::high_resolution_clock Clock;

class Milliseconds : public std::chrono::milliseconds
{
public:
    typedef std::chrono::milliseconds Base;
    typedef Base::rep Type;

    using Base::Base;
};

inline Milliseconds::Type millisecondsSinceEpoch()
{
    return std::chrono::duration_cast<Milliseconds::Base>(Clock::now().time_since_epoch()).count();
    //duration_cast<Milliseconds> ERROR!
}

int main() {
    using namespace std;
    cout << millisecondsSinceEpoch() << endl;
    return 0;
}

3 个答案:

答案 0 :(得分:2)

标准duration_cast只能用于转换为duration的特化。 [time.duration.cast] / P1:

template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
     

备注:除非ToDurationduration的实例化,否则此函数不应参与重载决策。

如果ToDuration不是duration的特化,则签名将从重载解析中删除(通过SFINAE或类似技术),并且除非另一个名为{{1}的函数模板,否则调用将失败}可用。

答案 1 :(得分:1)

在您的代码中替换duration_cast<Milliseconds>时,Visual C ++ 2015 RC会发出以下错误:

error C2770: invalid explicit template argument(s) for 'enable_if<std::chrono::_Is_duration<_Ty>::value,_To>::type std::chrono::duration_cast(const std::chrono::duration<_Rep,_Period> &)'

std::chrono::_Is_duration<_Ty>特征是MSVC中使用的标准库的内部实现细节;它是根据标准使事情工作并使错误消息更容易理解的:你需要给duration_cast一个模板参数,它实际上是std::chrono::duration模板的特化。在这种情况下,不考虑派生到基础的关系。

标准(N4431草案)中的

[20.12.5.7]具有以下描述:

template <class ToDuration, class Rep, class Period>
  constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
  

备注:除非ToDurationduration的实例化,否则此函数不应参与重载决策。

在从函数调用[14.8.2.1]的参数类型中推导出模板参数时,会考虑基类模板特化,但在将类参数与类模板部分特化[14.5.5.1]匹配时则不会考虑这种情况,这就是_Is_duration特征。

答案 2 :(得分:1)

您需要提供自己的duration_cast

template< typename my_dest, typename my_source >
my_dest duration_cast( my_source const & value )
    { return duration_cast< my_dest::duration >( value ); }

不允许将其放在namespace std::chrono中,因此您无法将其称为std::chrono::duration_cast。另一种方法是将using std::chrono::duration_castusing my_namespace::duration_cast添加到您的命名空间,并使用相应的调用进行限定。 (在示例中,您没有使用命名空间,因此只需要using std ...。