C++ 叮当作响';s libc++;:在std::chrono::duration的定义中使用long-long
在32位平台上的libc++中,C++ 叮当作响';s libc++;:在std::chrono::duration的定义中使用long-long,c++,c++11,clang,libc++,C++,C++11,Clang,Libc++,在32位平台上的libc++中,int64\t被定义为long的别名。在64位平台上:long 另一方面,在定义std::chrono::duration别名时,您可以发现long-long被随意使用: typedef duration<long long, nano> nanoseconds; typedef duration<long long, micro> microseconds; typedef duration<long
int64\t
被定义为long
的别名。在64位平台上:long
另一方面,在定义std::chrono::duration
别名时,您可以发现long-long
被随意使用:
typedef duration<long long, nano> nanoseconds;
typedef duration<long long, micro> microseconds;
typedef duration<long long, milli> milliseconds;
typedef duration<long long > seconds;
typedef duration< long, ratio< 60> > minutes;
typedef duration< long, ratio<3600> > hours;
是一个相当可移植的解决方案。但是对于libc++的chrono
来说,这是不正确的。除了编写类似于
的自己的逻辑之外,没有其他可移植的方法。即,定义两个附加的foo
定义,分别采用long
和unsigned long
或者另一个例子:
foo(int8_t);
foo(int16_t);
foo(int32_t);
foo(int64_t);
在这种情况下,调用foo(duration.count())
是不明确的
那么使用long-long
的意义是什么呢?它不大于long
,但是它的秩大于long
,所以不能隐式强制转换
这是libc++
开发人员的疏忽吗
我之所以提出这个问题,是因为mongodb的驱动程序无法在x64 FreeBSD安装上编译。原因看起来很愚蠢。例如,gcc在
std::chrono::duration
的定义中使用了int64_t
,因此它按照预期进行编译。标准只要求seconds
是duration
的类型定义,其比率为1,“有符号整数类型至少为35位”。所以libc++的实现是正确的
虽然使用int64\t
在您的特定情况下会降低可移植性,但这只会让您走得更远。MSVC也使用long-long
,而不是int64\u t
。(尽管在这种情况下,它们是相同的类型。)该标准不保证持续时间int64\t
,因此,即使多个实现使用它,依赖它也是不可移植的
这里的问题不是libc++的实现做了什么坏事。问题是C++的整数类型有点古怪,尽管intNN\t
类型很方便,但它们并不能让您完全摆脱对底层类型的了解。特别是,试图用这些typedef为foo
创建一个完整的重载集是错误的;正是因为您遇到的问题,您需要查找底层类型:重载集可能包含也可能不包含long
,最终您将遇到该类型。它发生在libc++的duration
typedefs上,而不是发生在其他情况下,这只是巧合
是的,这是一个糟糕的情况,但这个特定的问题只是更大问题的一个小症状。标准不需要特定的整数类型来表示持续时间。它确实要求该类型可用作
rep
成员类型,因此您可以使用(例如,std::chrono::duration::seconds::rep
作为适合以秒为单位存储值的类型。我可以就这个问题发表一些权威性的意见,因为我是编写此代码的人。尽管其他两个答案都很好,我已经把它们投了更高的票
是的,我确实考虑过这些类型,并考虑用int\u t*
typedef
s来定义它们
对于那些必须超过32位的重复,我选择了long-long
,其余的则选择long
。后者是在知道将目标从i386更改为x86_64时,long
将从32位更改为64位的情况下完成的
如果我改为使用int\u t*
typedef
s,很可能其他人也会抱怨这种设计中的歧义问题(比如foo(int)
和foo(long-long)
)。很难取悦所有人
我注意到,在mongodb标题mongo/src/mongo/util/time\u support.h中,它说:
using Microseconds = stdx::chrono::microseconds;
using Milliseconds = stdx::chrono::milliseconds;
using Seconds = stdx::chrono::seconds;
using Minutes = stdx::chrono::minutes;
using Hours = stdx::chrono::hours;
这很容易看起来像:
using Microseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::microseconds::period>;
using Milliseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::milliseconds::period>;
using Seconds = stdx::chrono::duration<std::int64_t, stdx::chrono::seconds::period>;
using Minutes = stdx::chrono::duration<std::int64_t, stdx::chrono::minutes::period>;
using Hours = stdx::chrono::duration<std::int64_t, stdx::chrono::hours::period>;
使用微秒=stdx::chrono::duration;
使用毫秒=stdx::chrono::duration;
使用秒=stdx::chrono::duration;
使用分钟=stdx::chrono::duration;
使用小时=stdx::chrono::duration;
也就是说,
库使客户可以非常轻松地创建自定义单元。听起来这可能是一个很好的解决方案,适用于mongodb有64位平台,其中long
为32位。检查LP64和LLP64平台之间的差异。请注意,这甚至是特定于编译器的,不仅针对平台,尽管通常存在某些约定。@UlrichEckhardt当然有,但这有什么用呢?库定义了
,所以为什么不将它用于上述库的另一部分的可移植性呢?我的观点是,你的前导句是错误的,而且,如果我理解你的问题,它是完全无关的!这不是归结为一个问题吗“为什么在一个平台上用uint64_t
定义duration
,在另一个平台上用long
定义?”顺便问一下:你有关于mongodb构建问题的链接吗?@UlrichEckhardt问题将很快报告。真正的问题是为什么libc++的开发人员让库用户的生活变得更艰难。这里的问题到底是什么?在整数类型系统的问题上完全同意你的观点。多亏了C
它完全搞定了。另一方面,您会期望这种渐进式库的开发人员有更多的意识:(我的论点是:我坚信,在C++11委员会中,通过采用
,在不同平台上解决了某些整数类型的不同大小的可移植性问题,迈出了一小步。很少看到库本身的实现不使用引入的类型,原因相同:可移植性。
using Microseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::microseconds::period>;
using Milliseconds = stdx::chrono::duration<std::int64_t, stdx::chrono::milliseconds::period>;
using Seconds = stdx::chrono::duration<std::int64_t, stdx::chrono::seconds::period>;
using Minutes = stdx::chrono::duration<std::int64_t, stdx::chrono::minutes::period>;
using Hours = stdx::chrono::duration<std::int64_t, stdx::chrono::hours::period>;