Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: bitmask библиотека  (Прочитано 150 раз)
0 Пользователей и 1 Гость смотрят эту тему.
oktonion
Постоялец

ru
Offline Offline

« : 15-10-2017 12:02 » 

Здравствуйте,

ищу библиотеку/класс/кусок кода для удобной работы с bitmask для старого стандарта C++. Все что предлагают просторы интернета основано на std::bitset для C++11. Если у кого то есть готовое решение или ссылка на такое, а так же просто мысли как такой класс лучше организовать средствами C++ 98 того же, буду признателен.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 15-10-2017 15:31 » 

Тут не написано, что данный шаблон специфичен для С++11 и выше. А в принципе, если только он тебе нужен. Можно взять его исходник. И причесать его к твоему компилятору.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
oktonion
Постоялец

ru
Offline Offline

« Ответ #2 : 16-10-2017 17:39 » 

Мне скорее нужно готовое решение чтобы не изобретать своего велосипеда удобного класса. std::bitset всегда идут в паре с новыми enum class из C++11 что в общем то логично, хотелось бы узнать может кто сталкивался с такой задачей.
« Последнее редактирование: Вчера в 14:35 от oktonion » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 16-10-2017 22:13 » 

Класс std::bitset входит в STL C++98. В С++11 его расширили. Ничего не мешает использовать соответствующую версию.
http://www.cplusplus.com/reference/bitset/bitset/
Примеры оттуда, собранные с ключом -std=c++98, компилятся без вопросов.
« Последнее редактирование: Вчера в 06:04 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.

Хз, я не очень просто не очень во всё это верю, во всякие там сатурны и прочую поебень.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #4 : Вчера в 02:54 » 

 Насчет самого компилятора так и ничего и не узнали. Может он какой то специфический. Который не поддерживает даже стандарты своего времени.
Твкже не понятна полностью задача. тебе нужен полный функционал класса или работа с битами?
« Последнее редактирование: Вчера в 02:58 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
oktonion
Постоялец

ru
Offline Offline

« Ответ #5 : Вчера в 14:57 » 

Компилятор там действительно специфический, но по сути это смесь Watcom C и gcc древнего с обвязкой поверх. Уверен что std::biset там в каком то виде есть, вопрос в том что для полного решения нужна (везде используется) связка enum class + std::bitset, чего там явно нет.
Мне нужна работа именно с масками в формате класса/классов. То есть установка/снятие последовательности бит, инверсия по маске и т.п., но типобезопасно и удобно. Я уже было ринулся писать свое решение, но подумал что наверное, как обычно, все написано до нас.

Что-то в духе:
Код:
enum Flags
{
    flag1= 0x00,
    flag2 = 0x01,
    flag3 = 0x02,
    flag4 = 0x04,
    flag5= 0x08,
};

bitmask<int, Flags> bm;

bm.set(flag1 | flag2);
bm |= flag3;
bm.flip(flag1);


Проблемы написать такое вроде и нет, но с другой стороны под C++98 ничего не нашел, да и при реализации возникают вопросы сразу же.
Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : Сегодня в 04:19 » 

oktonion, а вот так твой компилятор умеет ?

Код: (C++)
struct Flags
{
        UINT8 flag1:1;
        UINT8 flag2:1;
        UINT8 flag3:1;
        UINT8 flag4:1;
        UINT8 flag5:1;
        UINT8 :3;//ещё три бита осталось

        Flags()
        {
                memset(this,0,sizeof(*this));
        }
};

Flags bm;

bm.flag1=1;
bm.flag2=1;
bm.flag3=1;
bm.flag1=~bm.flag1;
« Последнее редактирование: Сегодня в 04:21 от Алексей++ » Записан

oktonion
Постоялец

ru
Offline Offline

« Ответ #7 : Сегодня в 06:31 » 

Битовые поля умеет.
Вопрос не в том как получить доступ к битам (хоть побитовыми всякими |, &, ^, хоть поля), я видимо плохо описал что мне нужно из функциональности такого класса.
Задача в следующем:
Есть переменная типа T (размерности N bit), типы целые простые - int, unsigned, long, long long, short и т.п. Это переменная хранит набор заранее определенных флагов типа T1 (в общем то совпадает с типом T). Нужно дать простой и типобезопасный способ пользователю устанавливать и снимать, преобразовывать и др. операции с этими заранее определенными флагами над переменной.
Я могу понять как сделать такой класс для работы с одним флагом - делаю отдельный enum для флагов, описываю операции для работы только с этим типом enum'а и вот пользователь может работать с переменной только с помощью определенных флагов, а если он попытается писать туда какую либо ахинею, то компилятор ругнется. Но не будет работы с флагами тогда объединенными по или к примеру и т.д. Тогда нужен класс еще для безопасного флага вместо enum выходит - это в C++11 как раз решается enum class, где перегружаются операции (и, или, не и т.п.) и пишутся для них методы с понятными именами. Вот может есть что то подобное написанное под C++98 уже.
Важно по возможности закрыть все способы пользователю отстрелить себе ногу, потому как установка неверной последовательности бит в переменную (отличную от флагов или их комбинации) приведет к неопределенному поведению.
Поясню кодом :
Код: (C++)
        template<class MaskT, class FlagT>
        class bitmask
        {
        public:
                bitmask(const MaskT &val) :
                        _val(val)
                {
                }

                bitmask& set(const FlagT &flag)
                {
                        _val |= flag;
                        return *this;
                }
                /* нельзя, т.к. можно будет установить любую комбинацию флагов, отличную от комбинации в FlagT
                bitmask& set(const MaskT &flags)
                {
                        _val |= flags;
                        return *this;
                }
                */

        private:
                MaskT _val;
        };

        enum eFlags
        {
           flag1 = 0x00,
           flag2 = 0x01,
           flag3 = 0x02,
           flag4 = 0x04,
           flag5 = 0x08,
        };

bitmask<int, eFlags> bm(0);
bm.set(flag1); // окей, по "или" безопасно выставляем флаг в переменную
bm.set(flag1 | flag2); // хотелось бы так, но уже не выйдет
« Последнее редактирование: Сегодня в 11:48 от oktonion » Записан
Алексей++
кот глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : Сегодня в 07:07 » 

oktonion, примени маску разрешённых битов

Код:
enum eFlags
        {
           flag1 = 0x00,
           flag2 = 0x01,
           flag3 = 0x02,
           flag4 = 0x04,
           flag5 = 0x08,

           mask=(flag1|flag2|flag3|flag4|flag5),
        };

 и в методах класса после любого телодвижения  накладывай маску на хранилище:

Код:
_val &= mask;

компилятор ругаться не будет, но неадекватное значение задать будет невозможно.

Также в дебажном рантайме можно ввести проверку, и при (_val & ~mask)!=0 выкидывать сообщение (но это уже по вкусу)
Записан

oktonion
Постоялец

ru
Offline Offline

« Ответ #9 : Сегодня в 13:32 » new

Как вариант. Но хочется чтобы ругался. В итоге все же пишу свое. Для побитого или к примеру:
Код: (C++)
namespace cppbitmasks
{
        template<class MaskT, class FlagT>
        class bitmask
        {
        public:
                bitmask() :
                        _val(MaskT())
                {
                }

                bitmask(const FlagT &flag) :
                        _val(flag)
                {
                }

                bitmask(const bitmask &other) :
                        _val(other._val)
                {
                }

                inline bitmask& set(const FlagT &flag)
                {
                        _val |= flag;
                        return *this;
                }

                inline bitmask& set(const bitmask &mask)
                {
                        _val |= mask._val;
                        return *this;
                }

                inline bitmask& operator|(const bitmask<MaskT, FlagT> &flag2)
                {
                        return set(flag2);
                }

                inline bitmask& operator|(const FlagT &flag2)
                {
                        return set(flag2);
                }

                bitmask& operator=(const bitmask &other)
                {
                        _val = other._val;
                        return *this;
                }

        private:
                MaskT _val;
        };

        template<class MaskT, class FlagT>
        inline bitmask<MaskT, FlagT>  &operator|(const FlagT &flag1, bitmask<MaskT, FlagT> &flag2)
        {
                return flag2 | flag1;
        }
}

Использование:

Код: (C++)
using namespace cppbitmasks;

enum eFlags
{
        flag1 = 0x00,
        flag2 = 0x01,
        flag3 = 0x02,
};

enum eFlags2
{
        flag4 = 0x04,
        flag5 = 0x08,
};

//определяем оператор для самого enum
bitmask<int, eFlags>  operator|(const eFlags &flag1, const eFlags &flag2)
{
        bitmask<int, eFlags> bm(flag1);
        return bm | flag2;
}

int main()
{
        bitmask<int, eFlags>  bm;

        flag3 | flag3; // ok, в bitmask преобразуется
        flag3 | bm; // ok, в bitmask преобразуется
        bm = flag3 | flag3; // ok
        bm = bm | flag3 | bm | flag2; // ok
        a.set(flag3 | flag2); // ok

        bm = flag3 | flag4; // ошибка компиляции
        a = a | flag3 | a | flag4; // ошибка компиляции
        a.set(flag3 | flag4); // ошибка компиляции

        return 0;
}

Пока что глупость написана в плане того что оператор изменяет значение, но направление гдето такое
« Последнее редактирование: Сегодня в 14:27 от oktonion » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines