int64_t 和类似类型是否有可移植的文字后缀?

Pro*_*awn 7 c++ portability c++17

我试图理解 std::variant:

#include <cstdint>
#include <variant>

std::variant<int64_t, double> v;
Run Code Online (Sandbox Code Playgroud)

我想分配一个 int64_t 变体:v = 5L; 它在 x86_64 上编译,因为 int64_t 很长。但它不能在 arm 上编译,因为 int64_t 很长。类型推导现在在 int64_t 和 double 之间有两个相等的选择来转换我的数字,所以它拒绝了。使用 variant<int64_t, string> 我什至不会注意到转换,因为只有一个可用并且编译器会接受它。

类似问题:v = 5LL;现在 arm / 32 位很好,但 x86_64 不再适用。

我在两个平台上都进行了编译,但这(有时)是一种类型转换,具有我无法预见的潜在副作用:v = int64_t(5LL);. 如果没有 LL,我什至无法表达 32 位 int 之外的值。

INT64_C 宏似乎是表达这一点的最便携和最安全的方式:v = INT64_C(5); 但这不再适合读写了。

对于可移植的 int64_t 是否有类似 L/LL 的文字后缀?

eer*_*ika 5

不,固定宽度整数别名没有标准文字。

一种潜在的解决方法是使用std::variant<long long, double> v;. 尽管long long理论上不能保证完全是 64 位(它可能更宽,但不会更窄),但实际上在long long当今支持的每个系统上都是 64 位。好处是long long当然有标准的文字。潜在的缺点是理论上尺寸情况将来可能会发生变化。

更通用的解决方案是放弃使用文字后缀,而是使用强制转换:v = static_cast<int64_t>(5);

另一个解决方案是创建一个用户定义的文字,如评论中链接的答案所示:

constexpr std::int64_t operator "" _int64(unsigned long long v)
{ return static_cast<std::int64_t>(v); }
Run Code Online (Sandbox Code Playgroud)

有人建议将这样的文字添加到标准库中:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1280r2


与此相关的是,有人建议为std::size_t和添加文字std::ptrdiff_t。该提案建议使用核心语言文字而不是标准库文字:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0330r3