SubtypeVariant.hpp
1 #pragma once
2 #include <ossia/detail/variant.hpp>
3 
4 #include <boost/mp11/algorithm.hpp>
5 
6 #include <type_traits>
7 
8 namespace score
9 {
10 namespace detail
11 {
16 template <typename T>
18 {
19  const T& impl;
20 
21  template <typename Arg>
22  auto operator()(Arg&& arg) const
23  {
24  return impl(*std::forward<Arg>(arg));
25  }
26 
27  auto operator()() const { return impl(); }
28 };
29 
30 template <typename Variant, typename Base>
31 Variant make_subtype_variant(const Base&)
32 {
33  // The type does not match any
34  // in the proposed types for the variant.
35  return Variant{};
36 }
37 
38 template <typename Variant, typename Base, typename Arg, typename... SubArgs>
39 Variant make_subtype_variant(Base& base)
40 {
41  if(auto derived = dynamic_cast<Arg*>(&base))
42  {
43  return Variant(derived);
44  }
45 
46  return make_subtype_variant<Variant, Base, SubArgs...>(base);
47 }
48 
49 template <typename Variant, typename Base, typename Arg, typename... SubArgs>
50 Variant make_subtype_variant(const Base& base)
51 {
52  if(auto derived = dynamic_cast<const Arg*>(&base))
53  {
54  return Variant(derived);
55  }
56 
57  return make_subtype_variant<Variant, Base, SubArgs...>(base);
58 }
59 }
60 
70 template <typename Base, typename... Args>
72 {
73  using arg_list = ossia::variant<Args...>;
74  using ptr_list = boost::mp11::mp_transform<std::add_pointer_t, arg_list>;
75 
76  ptr_list m_impl;
77 
78 public:
79  explicit SubtypeVariant(Base& b)
80  : m_impl(detail::make_subtype_variant<ptr_list, Base, Args...>(b))
81  {
82  }
83 
84  explicit SubtypeVariant(const Base& b)
85  : m_impl(detail::make_subtype_variant<ptr_list, Base, Args...>(b))
86  {
87  }
88 
89  template <typename F>
90  auto apply(F&& f)
91  {
92  if(m_impl)
93  {
94  return ossia::visit(detail::dereference_visitor<F>{f}, m_impl);
95  }
96  else
97  {
99  }
100  }
101 };
102 }
Tools to build a variant type from classes in a same hierarchy.
Definition: SubtypeVariant.hpp:72
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Proxy visitor that dereferences before calling the actual visitor.
Definition: SubtypeVariant.hpp:18