builderutils.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright (C) 2020 The Qt Company Ltd.
  2. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
  3. #pragma once
  4. #include <functional>
  5. #include <tuple>
  6. // C++14 compatible apply implementation
  7. namespace detail {
  8. template<class F, class Tuple, std::size_t... I>
  9. constexpr auto apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
  10. -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...))
  11. {
  12. return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
  13. }
  14. }
  15. template<class F, class Tuple>
  16. constexpr auto apply(F&& f, Tuple&& t)
  17. -> decltype(detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
  18. std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}))
  19. {
  20. return detail::apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
  21. std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{});
  22. }
  23. namespace Building {
  24. class NestId {};
  25. template <typename Id, typename Arg>
  26. class IdAndArg
  27. {
  28. public:
  29. IdAndArg(Id, const Arg &arg) : arg(arg) {}
  30. const Arg arg; // FIXME: Could be const &, but this would currently break bindTo().
  31. };
  32. // The main dispatcher
  33. template<typename X, typename Id, typename P>
  34. void doit(X x, Id id, P p);
  35. template <typename X> class BuilderItem
  36. {
  37. public:
  38. // Property setter
  39. template <typename Id, typename Arg>
  40. BuilderItem(IdAndArg<Id, Arg> && idarg)
  41. : apply([&idarg](X *x) { doit(x, Id{}, idarg.arg); })
  42. {}
  43. // Nested child object
  44. template <typename Inner>
  45. BuilderItem(Inner && p)
  46. : apply([&p](X *x) { doit(x, NestId{}, std::forward<Inner>(p)); })
  47. {}
  48. const std::function<void(X *)> apply;
  49. };
  50. #define QTC_DEFINE_BUILDER_SETTER(name, setter) \
  51. class name##_TAG {}; \
  52. template <typename ...Args> \
  53. inline auto name(Args &&...args) { \
  54. return Building::IdAndArg{name##_TAG{}, std::tuple<Args...>{std::forward<Args>(args)...}}; \
  55. } \
  56. template <typename L, typename ...Args> \
  57. inline void doit(L *x, name##_TAG, const std::tuple<Args...> &arg) { \
  58. apply(&L::setter, std::tuple_cat(std::make_tuple(x), arg)); \
  59. }
  60. } // Building