Apple clang:为什么我不能从 std::chrono::nanoseconds 创建 time_point
Apple clang: Why can I not create a time_point from std::chrono::nanoseconds
鉴于这个最小的代码示例,我在其中从 std::chrono::nanoseconds 构造了一个 time_point:
#include <chrono>
int
main()
{
std::chrono::time_point<std::chrono::system_clock> t{std::chrono::nanoseconds{10}};
(void)t;
}
根据我的阅读,这应该没问题 specification:纳秒是一个持续时间,time_point 支持从一个持续时间构建。实际上,使用 x86_64 clang 11.0.0:
可以很好地编译
然而,在我的 Mac 上,当我编译它时,我收到以下错误:
clang++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:6:54: error: no matching constructor for initialization of 'std::chrono::time_point<std::chrono::system_clock>'
std::chrono::time_point<std::chrono::system_clock> t{std::chrono::nanoseconds{10}};
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1355:28: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::chrono::nanoseconds' (aka 'duration<long long, ratio<1LL, 1000000000LL> >') to
'const std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1, 1000000> > >' for 1st argument
class _LIBCPP_TEMPLATE_VIS time_point
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1355:28: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'std::chrono::nanoseconds' (aka 'duration<long long, ratio<1LL, 1000000000LL> >') to
'std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1, 1000000> > >' for 1st argument
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1369:70: note: candidate constructor not viable: no known conversion from 'duration<[...], ratio<[...], 1000000000>>' to 'const duration<[...], ratio<[...], 1000000>>' for 1st argument
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit time_point(const duration& __d) : __d_(__d) {}
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1374:5: note: candidate template ignored: could not match 'time_point' against 'duration'
time_point(const time_point<clock, _Duration2>& t,
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1368:61: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 time_point() : __d_(duration::zero()) {}
^
1 error generated.
这是我正在使用的 clang:
$ clang++ --version
Apple clang version 12.0.0 (clang-1200.0.26.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
有人可以帮助我了解我是在处理 Apple clang 编译器中的编译器错误,还是在 x86_64 clang 中遇到了不受严格支持的问题?
更新
霍华德的回答指出了我的问题并提供了解决方案。只是为了使事情明确并且可能避免混淆其他人,这是我最初的问题,从上面引用:
Can someone help me understand whether I'm dealing with a compiler bug
in the Apple clang compiler or whether I'm getting away with something
in the x86_64 clang that isn't strictly supported?
这道题的正确答案是“都不是”。我最初在 Linux 上用 libstd c++ 编写了我的代码,它具有纳秒作为 time_point 的默认持续时间。我没有意识到这一点,但我的代码隐含地假定了这一点。当我尝试在 Apple clang 中构建从纳秒持续时间构造 time_point 的相同代码时,它无法编译,因为 time_point 默认为微秒。因此,编译器警告我截断,这很有帮助,当然不是编译器错误。一旦我按照霍华德的建议做了,并用纳秒明确地实例化了我的所有 time_point,我在任何一个系统上都不再有问题。
time_point
有两个构造函数需要持续时间。
constexpr explicit time_point(const duration& d);
template<class Duration2>
constexpr time_point(const time_point<clock, Duration2>& t);
第一个持续时间与时钟提供的持续时间相同。
第二个应该将持续时间转换为时钟提供的持续时间。
顺便说一句,如果我没看错的话,你要求的是纪元的开始 + 10ns。
如果 system_clock
的分辨率大于 10ns(确实如此),那么它应该被截断为零,你会得到一个 time_point
等于纪元的开始。
现在,关于为什么这不能编译。
第二个构造函数是 SFINAE,它基于 Duration2
是否可转换为 duration
(又名 system_clock::duration
)。
而且(至少对于 libc++ 而言),这似乎是错误的。即,这失败了:
static_assert (std::is_convertible<
std::chrono::nanoseconds,
std::chrono::system_clock::duration
>
::value, "");
然后问题变成了 - 应该 这是错误的。
后来:霍华德的回答让我相信这在 Mac OS.
上应该是错误的
如果您在 Linux 上使用 libstdc++,那么 std::chrono::system_clock::duration
实际上是 std::chrono::nanoseconds
,因此它使用第一个构造函数。
在 macOS 上,system_clock::duration
是 microseconds
。 chrono 库可以防止您意外地将 nanoseconds
截断为 microseconds
并丢失信息。您可以手动进行截断(例如 duration_cast
),或者您可以更改 time_point
的类型,以便它可以存储 nanoseconds
:
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>
t{std::chrono::nanoseconds{10}};
在 C++20 中,上述行可以简化为:
std::chrono::sys_time t{std::chrono::nanoseconds{10}};
t
的类型和值将保持不变。 sys_time
只是基于 system_clock
.
的 time_point
的类型别名
鉴于这个最小的代码示例,我在其中从 std::chrono::nanoseconds 构造了一个 time_point:
#include <chrono>
int
main()
{
std::chrono::time_point<std::chrono::system_clock> t{std::chrono::nanoseconds{10}};
(void)t;
}
根据我的阅读,这应该没问题 specification:纳秒是一个持续时间,time_point 支持从一个持续时间构建。实际上,使用 x86_64 clang 11.0.0:
可以很好地编译然而,在我的 Mac 上,当我编译它时,我收到以下错误:
clang++ -g -Wall -Werror -std=c++17 test.cc -o test
test.cc:6:54: error: no matching constructor for initialization of 'std::chrono::time_point<std::chrono::system_clock>'
std::chrono::time_point<std::chrono::system_clock> t{std::chrono::nanoseconds{10}};
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1355:28: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::chrono::nanoseconds' (aka 'duration<long long, ratio<1LL, 1000000000LL> >') to
'const std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1, 1000000> > >' for 1st argument
class _LIBCPP_TEMPLATE_VIS time_point
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1355:28: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'std::chrono::nanoseconds' (aka 'duration<long long, ratio<1LL, 1000000000LL> >') to
'std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1, 1000000> > >' for 1st argument
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1369:70: note: candidate constructor not viable: no known conversion from 'duration<[...], ratio<[...], 1000000000>>' to 'const duration<[...], ratio<[...], 1000000>>' for 1st argument
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit time_point(const duration& __d) : __d_(__d) {}
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1374:5: note: candidate template ignored: could not match 'time_point' against 'duration'
time_point(const time_point<clock, _Duration2>& t,
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/chrono:1368:61: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 time_point() : __d_(duration::zero()) {}
^
1 error generated.
这是我正在使用的 clang:
$ clang++ --version
Apple clang version 12.0.0 (clang-1200.0.26.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
有人可以帮助我了解我是在处理 Apple clang 编译器中的编译器错误,还是在 x86_64 clang 中遇到了不受严格支持的问题?
更新
霍华德的回答指出了我的问题并提供了解决方案。只是为了使事情明确并且可能避免混淆其他人,这是我最初的问题,从上面引用:
Can someone help me understand whether I'm dealing with a compiler bug in the Apple clang compiler or whether I'm getting away with something in the x86_64 clang that isn't strictly supported?
这道题的正确答案是“都不是”。我最初在 Linux 上用 libstd c++ 编写了我的代码,它具有纳秒作为 time_point 的默认持续时间。我没有意识到这一点,但我的代码隐含地假定了这一点。当我尝试在 Apple clang 中构建从纳秒持续时间构造 time_point 的相同代码时,它无法编译,因为 time_point 默认为微秒。因此,编译器警告我截断,这很有帮助,当然不是编译器错误。一旦我按照霍华德的建议做了,并用纳秒明确地实例化了我的所有 time_point,我在任何一个系统上都不再有问题。
time_point
有两个构造函数需要持续时间。
constexpr explicit time_point(const duration& d);
template<class Duration2>
constexpr time_point(const time_point<clock, Duration2>& t);
第一个持续时间与时钟提供的持续时间相同。 第二个应该将持续时间转换为时钟提供的持续时间。
顺便说一句,如果我没看错的话,你要求的是纪元的开始 + 10ns。
如果 system_clock
的分辨率大于 10ns(确实如此),那么它应该被截断为零,你会得到一个 time_point
等于纪元的开始。
现在,关于为什么这不能编译。
第二个构造函数是 SFINAE,它基于 Duration2
是否可转换为 duration
(又名 system_clock::duration
)。
而且(至少对于 libc++ 而言),这似乎是错误的。即,这失败了:
static_assert (std::is_convertible<
std::chrono::nanoseconds,
std::chrono::system_clock::duration
>
::value, "");
然后问题变成了 - 应该 这是错误的。
后来:霍华德的回答让我相信这在 Mac OS.
上应该是错误的如果您在 Linux 上使用 libstdc++,那么 std::chrono::system_clock::duration
实际上是 std::chrono::nanoseconds
,因此它使用第一个构造函数。
在 macOS 上,system_clock::duration
是 microseconds
。 chrono 库可以防止您意外地将 nanoseconds
截断为 microseconds
并丢失信息。您可以手动进行截断(例如 duration_cast
),或者您可以更改 time_point
的类型,以便它可以存储 nanoseconds
:
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>
t{std::chrono::nanoseconds{10}};
在 C++20 中,上述行可以简化为:
std::chrono::sys_time t{std::chrono::nanoseconds{10}};
t
的类型和值将保持不变。 sys_time
只是基于 system_clock
.
time_point
的类型别名