Reputation: 18561
My C++ program uses unsigned ints of different widths to express constraints on what data can be represented. For example, I have a file whose size is a uint64_t
, and I wish to read it in chunks with a buffer whose size is a size_t
. A chunk is the smaller of the buffer size and the (remaining) file size:
uint64_t file_size = ...;
size_t buffer_size = ...;
size_t chunk_size = std::min(buffer_size, file_size);
but this fails because std::min
requires that both parameters have the same type, so I must cast up and then back down:
size_t chunk_size = \
static_cast<size_t>(std::min(static_cast<uint64_t>)buffer_size, \
file_size));
This casting ought to be unnecessary, because it is obvious that min(size_t, uint64_t)
will always fit in a size_t
.
How can I write a generic min
function that takes two (possibly different) unsigned types, and whose return type is the smaller of the two types?
Upvotes: 6
Views: 2188
Reputation: 303277
If you want to explicitly cast to the smaller one, you should just tell the compiler that:
std::min<smaller_type>(buffer_size, file_size)
That's pretty explicit and everybody will understand what you're doing. I would just stick with that. You're providing the type you want at the point of call. That is more readable than hiding it behind a function template somewhere every time.
Although, given the potential overflow issues, you could do:
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);
}
Upvotes: 5