Type Driven User Interfaces

with Qt   and C++

Qt World Summit 2019 Berlin

Andreas Reischuck

Distributed System

Action Command Server Event Computation Update View

How can we design this?

Strong Types

struct Point {
    double x;
    double y;
    double z;
};
struct Point {
    double x;
    double y;
    double z;
    double weight;
};
struct Point {
    double x;
    double y;
    double z;
    double weight;
    double texX;
    double texY;
};
struct X { double v{}; };
struct Y { double v{}; };
struct Z { double v{}; };
struct Point {
    X x;
    Y y;
    Z z;
};
struct X { double v{}; };
struct Y { double v{}; };
struct Z { double v{}; };

using Point = std::tuple<X, Y, Z>;
template<class V, class /*Tag*/ >
struct Strong {
    V v{};
};
BarneyDellar StrongTypes CppOnSea

Strong Types in C++ - Barney Dellar [C++ on Sea 2019]

using X = Strong<double, struct XTag>;
using Y = Strong<double, struct YTag>;
using Z = Strong<double, struct ZTag>;
struct Point {
    X x;
    Y y;
    Z z;
};
using X = Strong<double, struct XTag>;
using Y = Strong<double, struct YTag>;
using Z = Strong<double, struct ZTag>;

using Point = std::tuple<X, Y, Z>;
using X = Strong<double, struct XTag>;
using Y = Strong<double, struct YTag>;
using Z = Strong<double, struct ZTag>;

using Point = AllOf<X, Y, Z>;

Data Schema

Existing Data Schemas

using Point = AllOf<X, Y, Z>;
using Points = SequenceOf<Point>;
using Geometry = AllOf<Points, Faces, Shaders>;
using Object = OneOf<Geometry, Light, Camera>;
using Scene = Hierarchy<ObjectId, Object>;
using Document = AllOf<Name, Scene>;
using Documents = EntitySet<DocId, Document>;
Slide1
Slide2
Slide3
Slide4
Slide5
Slide6
Slide7

Schema with C++ types

// recursive schema primitives:
template<class...> struct AllOf {};
template<class...> struct OneOf {};
template<class> struct SequenceOf {};
template<class Id, class>
struct EntitySet {};
template<class Id, class>
struct Hierarchy {};

Type driven Code generation

 

 

AllOf<...>
    -> std::tuple<...>;
 

 
template<class... Ts>
AllOf<Ts...> -> std::tuple<...>;
 

 
template<class... Ts>
StorageFor(AllOf<Ts...>)
-> std::tuple<...>;
 

 
template<class... Ts>
StorageFor(AllOf<Ts...>)
    -> std::tuple<StorageFor<Ts>...>;
template<class T>
using StorageFor =
    decltype(storageFor(adl, ptr<T>));
template<class... Ts>
auto storageFor(ADL, AllOf<Ts...> *)
-> std::tuple<StorageFor<Ts>...>;
Geburtstag
Action Command Server Event Computation Update View Schema ?

ViewModel

template<class T>
using ViewModelFor = decltype(
        viewModelFor(adl, ptr<T>));
template<class... Ts>
auto viewModelFor(ADL, AllOf<Ts...> *)
    -> AllOfView<Ts...>;
template<class... Ts>
class AllOfView : public QObject {
};

Woboq Verdigris

 

template<class... Ts>
class AllOfView : public QObject {
  W_OBJECT(AllOfView)
};
W_OBJECT_IMPL(AllOfView<Ts...>,
              template<class... Ts>)
template<class... Ts>
class AllOfView : public QObject {

  template<size_t I,
           class = std::enable_if_t<(I < sizeof...(Ts))>>
struct RegisterProperties {
    constexpr static auto property =
      w_cpp::makeProperty<QVariant>(
          property_name<I>, qvariant_name)
        .setGetter(&AllOfView::getPropertyValue<I>)
        .setSetter(&AllOfView::setPropertyValue<I>)
        .setNotify(&AllOfView::propertyChanged<I>);
};
  W_CPP_PROPERTY(RegisterProperties)
};
Action Command Server Event Computation Update View Schema

Recap

 

++ Advantages ++  

-- Disadvantages --

Links

andreas

 

hicknhackLogo new text

 

Work with us…

cppug

 

Give a Talk
⇒ get a Dresden tour

rebuild logo

Rebuild language project

 

Collaborate

Try out more!

Try out Type Driven Development!

Photo Credits

Thank you!

co_await question_ready()

Opaque Strong Types

struct PersonId
      : Strong<int, struct PersonIdTag>
{
    using Strong::Strong;
};
constexpr auto makeOpaque(
        Strong<int, struct PersonIdTag>)
    -> PersonId;
#define STRONG_OPAQUE(name, type, ...)                   \
  struct name : Strong<type, name##Tag, ##__VA_ARGS__> { \
    using Strong::Strong;                                \
  };                                                     \
  constexpr auto makeOpaqueType(Strong<                  \
    type, name##Tag, ##__VA_ARGS__>) -> name             \

STRONG_OPAQUE(PersonId, int);