Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing std::min/std::max for ints of heterogenous widths

Tags:

c++

c++11

min

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?

like image 863
ridiculous_fish Avatar asked Jul 11 '15 19:07

ridiculous_fish


1 Answers

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);
}
like image 131
Barry Avatar answered Sep 22 '22 00:09

Barry