【问题标题】:Writing std::min/std::max for ints of heterogenous widths为异质宽度的整数编写 std::min/std::max
【发布时间】:2015-09-30 09:48:33
【问题描述】:

我的 C++ 程序使用不同宽度的无符号整数来表达对可以表示哪些数据的约束。例如,我有一个大小为uint64_t 的文件,我希望使用大小为size_t 的缓冲区分块读取它。块是缓冲区大小和(剩余)文件大小中较小的一个:

uint64_t file_size = ...;
size_t buffer_size = ...;
size_t chunk_size = std::min(buffer_size, file_size);

但这失败了,因为std::min 要求两个参数具有相同的类型,所以我必须先向上然后再向下:

size_t chunk_size = \
    static_cast<size_t>(std::min(static_cast<uint64_t>)buffer_size, \
                                 file_size));

这个转换应该是不必要的,因为很明显min(size_t, uint64_t) 总是适合size_t

如何编写一个通用的min 函数,它采用两种(可能不同的)无符号类型,其返回类型是两种类型中较小的类型?

【问题讨论】:

  • 我在某处有一个实现,但我认为它很糟糕......而且它是 GPL,我不愿意重新授权它以满足 SO 的要求。
  • 挖掘出来并为那些可以使用 GPL3+ 的人提供一个要点:gist.github.com/o11c/0d5c10684d8fe713d7f3

标签: c++ c++11 min


【解决方案1】:

如果您想显式转换为较小的,您应该告诉编译器:

std::min<smaller_type>(buffer_size, file_size)

这很明确,每个人都会明白你在做什么。我会坚持下去。您在呼叫点提供您想要的类型。这比每次都将其隐藏在某个函数模板后面更具可读性。

尽管考虑到潜在的溢出问题,您可以这样做:

template <typename U, typename V>
using smaller_type = std::conditional_t<sizeof(U) < sizeof(V), U, V>;

template <typename U, typename V>
using larger_type = std::conditional_t<sizeof(V) < sizeof(U), U, V>;

template <typename U, typename V>
smaller_type<U, V> my_min(const U& u, const V& v) {
    return std::min<larger_type<U, V>>(u, v);
}

【讨论】:

  • 这优雅地解决了强制转换的需要,但代价是一些正确性。 std::min&lt;uint32_t&gt;(1, 1LLU&lt;&lt;32) 应该为 1 时为 0。
  • @ridiculous_fish 更新了函数模板解决方案。当然,您仍然会遇到签名问题。
  • 酷,我不知道 std::conditional。这非常方便!如果您修复代码以使其编译(供将来的搜索者使用),我会接受您的回答。
  • 未修复,但我会接受。如果你有机会请修复它(conditional_t -> 有条件的,缺少 typename 和 ::type)
  • @ridiculous_fish 这不是错误。 C++14 为类型特征引入了别名(参见conditional)。如果您没有 C++14 编译器,我建议您自己添加别名。 typename trait&lt;X&gt;::type 语法已成为过去。
猜你喜欢
  • 1970-01-01
  • 2011-08-02
  • 2020-10-12
  • 2021-04-25
  • 2012-11-05
  • 1970-01-01
  • 2019-03-03
  • 2019-08-04
  • 1970-01-01
相关资源
最近更新 更多