AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
unset.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12//
   13// Created by alex2 on 03.01.2021.
   14//
   15
   16#pragma once
   17
   18#include <AUI/Traits/concepts.h>
   19#include <AUI/Util/Assert.h>
   20#include <algorithm>
   21#include <ostream>
   22
   23#include <fmt/core.h>
   24
   25namespace ass {
   26
   27    template<typename T>
   28    struct unset_wrap {
   29    private:
   30        T stored;
   31        bool set = false;
   32
   33    public:
   34        unset_wrap() noexcept
   35        {
   36        }
   37
   38        template<typename V>
   39        unset_wrap(const V& v);
   40
   41        template<typename V>
   42        unset_wrap(V&& v);
   43
   44        T& operator*() {
   45            AUI_ASSERT(bool(*this));
   46            return stored;
   47        }
   48        const T& operator*() const {
   49            AUI_ASSERT(bool(*this));
   50            return stored;
   51        }
   52        T* operator->() {
   53            AUI_ASSERT(bool(*this));
   54            return &stored;
   55        }
   56        const T* operator->() const {
   57            AUI_ASSERT(bool(*this));
   58            return &stored;
   59        }
   60        T orDefault(const T& def) const {
   61            if (set) {
   62                return stored;
   63            }
   64            return def;
   65        }
   66
   67        template<typename Destination>
   68        void bindTo(Destination& destination) const {
   69            if (set) {
   70                destination = stored;
   71            }
   72        }
   73
   74        unset_wrap<T>& operator=(const unset_wrap<T>& v) noexcept;
   75
   76        template<aui::convertible_to<T> U>
   77        unset_wrap<T>& operator=(const unset_wrap<U>& v) noexcept;
   78
   79        bool operator==(const unset_wrap<T>& other) const {
   80            if (set != other.set) {
   81                return false;
   82            }
   83            if (set) {
   84                return stored == other.stored;
   85            }
   86            return true;
   87        }
   88        bool operator!=(const unset_wrap<T>& other) const {
   89            return !(*this == other);
   90        }
   91
   92        void reset() noexcept {
   93            set = false;
   94        }
   95
   96        operator bool() const {
   97            return set;
   98        }
   99
  100        struct unset_wrap_tag {};
  101    };
  102
  103    namespace detail::unset {
  104        template<typename T, aui::convertible_to<T> U>
  105        void init(unset_wrap<T>& wrap, T& dst, bool& set, const unset_wrap<U>& value) {
  106            if (value) {
  107                dst = static_cast<T>(*value);
  108                set = true;
  109            }
  110        }
  111        template<typename T, aui::convertible_to<T> U>
  112        void init(unset_wrap<T>& wrap, T& dst, bool& set, unset_wrap<U>&& value) {
  113            if (value) {
  114                dst = static_cast<T&&>(*value);
  115                set = true;
  116            }
  117        }
  118        template<typename T, aui::convertible_to<T> U>
  119        void init(unset_wrap<T>& wrap, T& dst, bool& set, U&& value) {
  120            dst = static_cast<T&&>(value);
  121            set = true;
  122        }
  123        template<typename T, aui::convertible_to<T> U>
  124        void init(unset_wrap<T>& wrap, T& dst, bool& set, const U& value) {
  125            dst = static_cast<T>(value);
  126            set = true;
  127        }
  128    }
  129
  130
  131    template<typename T>
  132    template<typename V>
  133    unset_wrap<T>::unset_wrap(const V& v)
  134    {
  135        detail::unset::init(*this, stored, set, v);
  136    }
  137
  138
  139    template<typename T>
  140    template<typename V>
  141    unset_wrap<T>::unset_wrap(V&& v)
  142    {
  143        detail::unset::init(*this, stored, set, std::forward<V>(v));
  144    }
  145
  146    template<typename T>
  147    unset_wrap<T>& unset_wrap<T>::operator=(const unset_wrap<T>& v) noexcept {
  148        detail::unset::init(*this, stored, set, v);
  149        return *this;
  150    }
  151
  152    template<typename T>
  153    template<aui::convertible_to<T> U>
  154    unset_wrap<T>& unset_wrap<T>::operator=(const unset_wrap<U>& v) noexcept {
  155        detail::unset::init(*this, stored, set, v);
  156        return *this;
  157    }
  158
  159}
  160
  161template <typename T> struct fmt::formatter<ass::unset_wrap<T>> {
  162    template<typename ParseContext>
  163    constexpr auto parse(ParseContext& ctx)
  164    {
  165        return ctx.begin();
  166    }
  167
  168    auto format(ass::unset_wrap<T> c, format_context& ctx) const {
  169        if (c) {
  170            return fmt::format_to(ctx.out(), "{}", *c);
  171        } else {
  172            return fmt::format_to(ctx.out(), "<unset>");
  173        }
  174    }
  175};
  176
  177template<typename T>
  178std::ostream& operator<<(std::ostream& o, const ass::unset_wrap<T>& wrap) {
  179    if (wrap) {
  180        o << *wrap;
  181    } else {
  182        o << "<unset>";
  183    }
  184    return o;
  185}
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
Definition unset.h:100
Definition unset.h:28