std::bitset to any integral conversion

mrgordonfreman
mrgordonfreman

Пример типичного использования.

При объявлении bitset знаем точное число бит.

std::bitset<16> flags;

Здесь тоже знаем точное число бит.

uint16_t flags_register;

А дальше получаем проблемный код.

flags_register = flags.to_ulong();

Размер unsigned long может быть 4 или 8 байт на разных платформах. Но нам не нужно ни 4, ни 8 байт, а только 2. Более того, to_ulong() может кидать исключения, но мы точно знаем, что исключений не будет.

Но код работает, и вроде бы ничего страшного. Потом решили запускать компилятор с флагом -Wconversion и получаем предупреждение

Warning: conversion to ‘uint16_t {aka short unsigned int}’ from ‘long unsigned int’ may alter its value [-Wconversion]
flags_register = flags.to_ulong();
                 ~~~~~~~~~~~~~~^~

Тогда в коде придется использовать сужающее преобразование

flags_register = static_cast<uint16_t>(flags.to_ulong());

Проблему решит добавление следующего метода

#include <type_traits>

template<std::size_t N>
class bitset
{
    // ...
    template<typename T>
    T as_integral() const noexcept
    {
        static_assert(std::is_integral<T>::value && N <= sizeof(T) * 8);
        //...
    }
    // ...
};

Также станет невозможным преобразовать bitset в число с меньшим количеством бит, и узнаем это на этапе компиляции

std::bitset<16> bs;
bs.as_integral<uint16_t>();
bs.as_integral<uint8_t>(); // COMPILATION ERROR HERE!
14
рейтинг
1 комментарий
Antervis
Возможно, тогда стоит добавить метод integral_t to_integral() const noexcept;, где integral_t определен как беззнаковый целочисленный тип минимального достаточного размера, чтобы вместить все биты, или unsigned long long.
Antervis
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).