AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
concepts.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#pragma once
   13
   14#include <AUI/api.h>
   15#include <concepts>
   16#include <utility>
   17#include <functional>
   18#include <type_traits>
   19#include "callables.h"
   20
   21namespace aui {
   22
   23    // the following concepts are partially copying stl functionality but android has no support for these
   24    template <class Derived, class Base>
   25    concept derived_from = std::is_base_of_v<Base, Derived> &&
   26                           std::is_convertible_v<const volatile Derived*, const volatile Base*>;
   27
   36    template<typename F, typename... Args>
   37    concept invocable = requires(F&& f, Args&&... args) {
   38        { std::invoke(f, std::forward<Args>(args)...) };
   39    };
   40
   41    template <class From, class To>
   42    concept convertible_to = std::is_convertible_v<From, To> && requires {
   43        static_cast<To>(std::declval<From>());
   44    };
   45
   46    template < class T >
   47    concept destructible = std::is_nothrow_destructible_v<T>;
   48
   49    template < class T, class... Args >
   50    concept constructible_from = destructible<T> && std::is_constructible_v<T, Args...>;
   51
   52    template<typename _Tp>
   54
   55    template< class T >
   57                                 constructible_from<T, T&> &&
   58                                 convertible_to<T&, T> &&
   59                                 constructible_from<T, const T&> &&
   60                                 convertible_to<const T&, T> &&
   61                                 constructible_from<T, const T> &&
   62                                 convertible_to<const T, T>;
   63
   64    namespace detail {
   65        template< class T, class U >
   66        concept SameHelper = std::is_same_v<T, U>;
   67    }
   68
   69    template< class T, class U >
   70    concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
   71
   72
   73
   74    template < class T, class U >
   75    concept common_reference_with = same_as<std::remove_reference_t<T>, std::remove_reference_t<T>> &&
   76                                    convertible_to<T, std::remove_reference_t<U>> &&
   77                                    convertible_to<U, std::remove_reference_t<T>>;
   78
   79    template< class LHS, class RHS >
   80    concept assignable_from = std::is_lvalue_reference_v<LHS> &&
   81                              common_reference_with<const std::remove_reference_t<LHS>&,
   82                                                    const std::remove_reference_t<RHS>&> &&
   83                              requires(LHS lhs, RHS&& rhs) {
   84        { lhs = std::forward<RHS>(rhs) } -> std::same_as<LHS>;
   85    };
   86    template< class T >
   87    concept swappable =
   88    requires(T& a, T& b) {
   89        std::swap(a, b);
   90    };
   91
   92
   93    template < class T >
   94    concept movable = std::is_object_v<T> &&
   95                      move_constructible<T> &&
   96                      assignable_from<T&, T> &&
   97                      swappable<T>;
   98
   99    template <class T>
  101                       movable<T> &&
  102                       assignable_from<T&, T&> &&
  103                       assignable_from<T&, const T&> &&
  104                       assignable_from<T&, const T>;
  105
  106    template<class T>
  108                                    requires { T{}; } &&
  109                                    requires { ::new T; };
  110
  111
  112    template <class T>
  114
  115    template <class T>
  116    concept regular = semiregular<T>;
  117
  118    template<class I>
  119    concept incrementable = regular<I> && requires(I i) {
  120        { i++ } -> std::same_as<I>;
  121    };
  122
  123
  124    template<typename F, typename... Args>
  125    concept predicate = requires(F&& f, Args&... args) {
  126        { f(args...) } -> same_as<bool>;
  127    };
  128
  129    // aui concepts
  130
  131    template<typename F, typename From, typename To>
  132    concept mapper = requires(F&& f, From&& from) {
  133        { std::invoke(f, std::forward<From>(from)) } -> aui::convertible_to<To>;
  134    };
  135
  136    template<typename F, typename ProducedObject>
  137    concept factory = requires(F&& f) {
  138        { std::invoke(f) } -> aui::convertible_to<ProducedObject>;
  139    };
  140
  144    template<typename T>
  145    concept arithmetic = std::is_arithmetic_v<T>;
  146
  147    template<typename T>
  148    concept unsigned_integral = std::is_unsigned_v<T>;
  149
  150    template<typename T>
  151    concept is_tuple = requires { std::tuple_size<T>::value; };
  152    static_assert(is_tuple<std::tuple<>>);
  153    static_assert(is_tuple<std::tuple<int>>);
  154    static_assert(is_tuple<std::tuple<double>>);
  155    static_assert(!is_tuple<int>);
  156    static_assert(!is_tuple<double>);
  157}
  158
  159// AObject-related concepts
  160class AString;
  161class AAbstractSignal;
  162class AAbstractThread;
  163class API_AUI_CORE AObjectBase;
  164
  165template <typename T>
  166concept AAnySignal = requires(T&& t) {
  167    typename std::decay_t<T>::emits_args_t;
  168
  169    // signal must be contextually convertible to bool (to check if there are any slots connected to it)
  170    { t } -> aui::convertible_to<bool>;
  171};
  172
  173template <typename C>
  174concept ASignalInvokable = requires(C&& c) { c.invokeSignal(nullptr); };
  175
  176template <typename Slot, typename Signal>
  177concept ACompatibleSlotFor = requires (Slot&& c) {
  178    { &std::decay_t<Slot>::operator() };
  179} || requires (Slot&& c) {
  180    typename aui::reflect::member<std::decay_t<Slot>>::args;
  181};
  182
  183class API_AUI_CORE AObjectBase;
  184
  186
  187template<aui::convertible_to<AObjectBase*> ObjectPtr, typename Invocable>
  188struct ASlotDef: ASlotDefBase {
  189    ObjectPtr boundObject;
  190    Invocable invocable;
  191    ASlotDef(ObjectPtr boundObject, Invocable invocable) : boundObject(std::move(boundObject)), invocable(std::move(invocable)) {}
  192};
  193
  194template <typename T>
  195concept APropertyReadable = requires(T&& t) {
  196    // Property must have Underlying type which it represents.
  197    typename std::decay_t<T>::Underlying;
  198
  199    // Property must have value() which returns its underlying value.
  201
  202    // Property must have boundObject() which returns AObjectBase* associated with this property.
  203    { t.boundObject() } -> aui::convertible_to<const AObjectBase*>;
  204
  205    // Property must be convertible to its underlying type.
  207
  208    // Property has operator* to explicitly pull the underlying value.
  210
  211    // Property has the "changed" signal
  212    { t.changed } -> AAnySignal;
  213};
  214
  215template <typename T>
  216concept APropertyWritable = requires(T&& t) {
  217    { t } -> APropertyReadable;
  218
  219    t.notify();
  220
  221    // Property has operator= overloaded so it can be used in assignment statement.
  222    { t = std::declval<typename std::decay_t<T>::Underlying>() };
  223};
  224
  225template <typename T>
  227
  228template <typename T>
  230
  231
  232template<AAnySignalOrProperty T>
  234
  235template<AAnySignal T>
  237    using args = typename T::emits_args_t;
  238};
  239template<AAnyProperty T>
  240struct AAnySignalOrPropertyTraits <T>{
  241    using args = std::tuple<typename T::Underlying>;
  242};
Base class for signal.
Definition AAbstractSignal.h:366
Represents an abstract thread. Not all threads are created through AThread - these are interfaced wit...
Definition AThread.h:32
Definition AObjectBase.h:24
Represents a Unicode character string.
Definition AString.h:38
Definition concepts.h:226
Definition concepts.h:229
Definition concepts.h:166
Definition concepts.h:177
Definition concepts.h:195
Definition concepts.h:216
Definition concepts.h:174
Concept shortcut to std::is_arithmetic_v.
Definition concepts.h:145
Definition concepts.h:80
Definition concepts.h:75
Definition concepts.h:50
Definition concepts.h:42
Definition concepts.h:56
Definition concepts.h:100
Definition concepts.h:107
Definition concepts.h:25
Definition concepts.h:47
Definition concepts.h:137
Definition concepts.h:119
Invokable concept.
Definition concepts.h:37
Definition concepts.h:151
Definition concepts.h:132
Definition concepts.h:94
Definition concepts.h:53
Definition concepts.h:125
Definition concepts.h:116
Definition concepts.h:70
Definition concepts.h:113
Definition concepts.h:87
Definition concepts.h:148
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition concepts.h:233
Definition concepts.h:185
Pointer to member type (not value) introspection.
Definition members.h:48