2

If I have compile time constant num_bits how can I get smallest integer type that can hold this amount of bits?

Of course I can do:

Try it online!

#include <cstdint>
#include <type_traits>
std::size_t constexpr num_bits = 19;
using T =
    std::conditional_t<num_bits <=  8, uint8_t,
    std::conditional_t<num_bits <= 16, uint16_t,
    std::conditional_t<num_bits <= 32, uint32_t,
    std::conditional_t<num_bits <= 64, uint64_t,
        void>>>>;

But maybe there exists some ready made meta function in standard library for achieving this goal?

I created this question only to find out single meta function specifically from standard library. But if you have other nice suggestions how to solve this task besides my proposed above solution, then please post such solutions too...


Update. As suggested in comments, uint_leastX_t should be used instead of uintX_t everywhere in my code above, as uintX_t may not exist on some platforms, while uint_leastX_t always exist.

Arty
  • 14,883
  • 6
  • 36
  • 69
  • 2
    There is nothing ready-made I am aware of. But to strictly satisfy your requirement you should probably be using `std::uint_leastX_t` instead of `uintX_t`, or even better use the actual integer types instead of aliases, but then it becomes difficult to include extended integer types if there are any. – user17732522 Oct 29 '22 at 09:34
  • @user17732522 Can you please tell what's the difference between uint_least32_t and uint32_t? If "least" version can be sometimes 64-bit, then it is not what I want. Actually I want smallest integer that can hold given bits, not ANY, and not Fast, but smallest. Can uint32_t be ever non-32? – Arty Oct 29 '22 at 11:25
  • 1
    The `least` versions are the smallest integer type of at least that bit width. It could be e.g. that `uint_least16_t` is 24 bit wide if there is no 16 bit wide integer type (and in that case `uint16_t` doesn't exist). But as I said, probably checking against the bit widths of `char`, `short`, `int`, `long` and `long long` is a better approach to really get the smallest one. But that doesn't capture extended integer types if there are any (but then, neither are the fixed-size types guaranteed to capture that). All of this matters only if you want to support more exotic platforms. – user17732522 Oct 29 '22 at 11:53
  • 1
    There is also the issue that e.g. on typical desktop platforms `uint64_t` may be either `unsigned long` or `unsigned long long` if both are 64 bit and then the question would be whether you want to guarantee that you choose the smaller rank, in which case `uint64_t` is unreliable and the bit widths of the integer types should be checked directly in order of rank. – user17732522 Oct 29 '22 at 12:02
  • 1
    You might also consider bit field or bit set if you want to optimize size. – Phil1970 Oct 29 '22 at 13:20
  • 1
    The reason for using the `least` variations rather than the exact size variations is that the exact size variations might not exist; the `least` will always exist. For example, on a hardware platform that does't have 32-bit integers `uint32_t` won't exist, but `uint_least32_t` will. – Pete Becker Oct 29 '22 at 13:40
  • @PeteBecker BTW, is there any special reason why alias type `uint_least24_t` doesn't exist and other multiples of 8 too? Only 8/16/32/64 exist as I see, at least after experimenting in godbolt. – Arty Oct 29 '22 at 19:53
  • @Arty -- nothing beyond the obvious fact that sizes other than powers of 2 tend to not exist. I don't think there's a deep reason for it. – Pete Becker Oct 29 '22 at 22:03

2 Answers2

1

There is currently no template type for this in the c++ standard library.

The standard library does have something to do the reverse of what you're looking for (std::numeric_limits<T>::max).

There is a proposal to add such functionality to the c++ standard library in p0102: "C++ Parametric Number Type Aliases". A similar question to yours has been asked on lists.isocpp.org/std-proposals, where p0102 was mentioned.

In case you're interested in / okay with using Boost, Boost has boost::int_max_value_t<V>, which is a struct defining type members least (smallest) and fast ("easiest to manipulate").

starball
  • 20,030
  • 7
  • 43
  • 238
0

No, there is no ready made meta function for this