如何将 `duration_cast` 用于派生的 class?
How to use `duration_cast` for a derived class?
我正在使用 std::chrono
清理我的计时器 class。除了我似乎无法将 duration_cast
应用于派生的 classes 之外,其他一切都很顺利。嗯,我让它以不同的方式工作,但我仍然想知道我错过了什么。
有关错误消息,请参阅 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;
}
Visual C++ 2015 RC 在代码中替换 duration_cast<Milliseconds>
时出现以下错误:
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>
trait 是 MSVC 中使用的标准库的内部实现细节;它的存在是为了让事情按照标准工作并使错误消息更容易理解:你需要给 duration_cast
一个模板参数,它实际上是 std::chrono::duration
模板的特化。在这种情况下不考虑派生到基础的关系。
[20.12.5.7]在标准(N4431草案)中有如下描述:
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Remarks: This function shall not participate in overload resolution unless ToDuration
is an instantiation of duration
.
Base class 模板特化在从函数调用 [14.8.2.1] 的参数类型推导模板参数时被考虑,但在将参数匹配到 class 模板部分特化 [ 14.5.5.1],这就是 _Is_duration
特征所发生的情况。
标准duration_cast
只能用于转换为duration
的特化。 [time.duration.cast]/p1:
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Remarks: This function shall not participate in overload resolution unless ToDuration
is an instantiation of duration
.
如果 ToDuration
不是 duration
的特化,则签名从重载决议中删除(通过 SFINAE 或类似技术),调用失败,除非另一个函数模板调用 duration_cast
可用。
您需要提供自己的 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_cast
和 using my_namespace::duration_cast
添加到您的名称空间,并用它来限定调用。 (在示例中,您没有使用名称空间,因此只需要 using std
…。)
我正在使用 std::chrono
清理我的计时器 class。除了我似乎无法将 duration_cast
应用于派生的 classes 之外,其他一切都很顺利。嗯,我让它以不同的方式工作,但我仍然想知道我错过了什么。
有关错误消息,请参阅 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;
}
Visual C++ 2015 RC 在代码中替换 duration_cast<Milliseconds>
时出现以下错误:
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>
trait 是 MSVC 中使用的标准库的内部实现细节;它的存在是为了让事情按照标准工作并使错误消息更容易理解:你需要给 duration_cast
一个模板参数,它实际上是 std::chrono::duration
模板的特化。在这种情况下不考虑派生到基础的关系。
[20.12.5.7]在标准(N4431草案)中有如下描述:
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Remarks: This function shall not participate in overload resolution unless
ToDuration
is an instantiation ofduration
.
Base class 模板特化在从函数调用 [14.8.2.1] 的参数类型推导模板参数时被考虑,但在将参数匹配到 class 模板部分特化 [ 14.5.5.1],这就是 _Is_duration
特征所发生的情况。
标准duration_cast
只能用于转换为duration
的特化。 [time.duration.cast]/p1:
template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Remarks: This function shall not participate in overload resolution unless
ToDuration
is an instantiation ofduration
.
如果 ToDuration
不是 duration
的特化,则签名从重载决议中删除(通过 SFINAE 或类似技术),调用失败,除非另一个函数模板调用 duration_cast
可用。
您需要提供自己的 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_cast
和 using my_namespace::duration_cast
添加到您的名称空间,并用它来限定调用。 (在示例中,您没有使用名称空间,因此只需要 using std
…。)