Пушыстый (_winnie) wrote,
Пушыстый
_winnie

Categories:

MayBe C++

Вот храним мы в переменной целое число. Иногда нам надо хранить не число, а факт того, что числа вообще нет. Например, функция пересечения двух линий хочет сообщить что нет точки пересечения вообще. Часто для этой цели используют "особые" значения которые вроде как бессмысленные. Например, -1 для int, или пустая строка для std::string.

Иногда делают баги, и забывают написать if на проверку бессмысленности значения. "Бессмысленное" значение вырывается в мир, и начинает участвовать в арифметических операциях или становится "особым" значением уже в другом месте.

Для того что бы явно записать факт "иногда тут ничего нет" используется обёртка над типом, внутри которой хранится булевский флажок. В boost есть тип boost::optional<T>. В Haskell есть Maybe T. В C# есть Nullable (для встроенных типов).


Хороший пример, почему лучше иметь тип в котором особое состояние "нету никакого int вообще": cначала человек получает -1 из системной функции типа getpid, а затем эта -1 попадает в killall. Смерть, разрушения, мертвый мак.

Есть ещё мой велосипед для C++, когда не хочется boost, без вложенных зависимостей:
MayBe<T> : https://github.com/dobrokot/may_be/blob/master/may_be.hpp

Если кто-то сможет помочь переписать с учетом strict aliasing - буду благодарен. Как с учетом strict aliasing вообще разместить объект типа T в массиве char[sizeof(T)] ? Русские коментарии на английские переведу сам, если вдруг окажется что штука нужная и нравится людям больше чем boost::optional :)

Примеры использования: https://github.com/dobrokot/may_be/blob/master/may_be_usage_example.cpp
#include "may_be.hpp" #include <iostream> struct Point { //тип, над которым мы будем эксперементировать. float x, y; Point(float x, float y): x(x), y(y) {} Point(): x(0), y(0) {} }; MayBe<Point> f1() { return MayBeEmpty; //вернуть пустоту. } MayBe<Point> f2() { return MayBeDefault; //вернуть объект, инициализированный по умолчанию } MayBe<int> f3() { return CreateMayBe(7); //вернуть конкретное значение. } int main() { { MayBe<Point> point; //инициализация с параметрами. if (true) MAYBE_INIT(point, Point(1, 2)); } { MayBe<Point> point; //Инициализация по умолчанию: if (true) point.ResetDefault(); } //Инициализация копированием существующего объекта: Point existing(3,4); MayBe<Point> point = CreateMayBe(existing); //использование: if (Point *p = point.Get()) //получить указатель, возможно NULL std::cout << p->x; if (point) std::cout << point->x; std::cout << std::endl; }
_Winnie C++ Colorizer
Tags: c++
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 25 comments